summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2021-03-30 17:06:55 +0300
committerSergei Golubchik <serg@mariadb.org>2021-05-19 22:54:13 +0200
commit83e529eced51aa965805e894349bbadd26881f3f (patch)
tree2f13b79cf5648498ee709424ea37105be730fcf3
parent496a14e18714ac3f0b686ec5f57bf88e96512d2f (diff)
downloadmariadb-git-83e529eced51aa965805e894349bbadd26881f3f.tar.gz
MDEV-18465 Logging of DDL statements during backup
Many of the changes was needed to be able to collect and print engine name and table version id's in the ddl log.
-rw-r--r--mysql-test/include/print_ddl_log.inc78
-rw-r--r--mysql-test/main/backup_lock.result21
-rw-r--r--mysql-test/main/backup_lock.test27
-rw-r--r--mysql-test/main/backup_lock_debug.result6
-rw-r--r--mysql-test/main/backup_lock_debug.test7
-rw-r--r--mysql-test/main/backup_log.inc155
-rw-r--r--mysql-test/main/backup_log.result241
-rw-r--r--mysql-test/main/backup_log.test39
-rw-r--r--mysql-test/main/backup_stages.result6
-rw-r--r--mysql-test/main/backup_stages.test3
-rw-r--r--mysql-test/suite/parts/r/backup_log.result278
-rw-r--r--mysql-test/suite/parts/r/backup_log_rocksdb.result15
-rw-r--r--mysql-test/suite/parts/t/backup_log.test63
-rw-r--r--mysql-test/suite/parts/t/backup_log_rocksdb.opt1
-rw-r--r--mysql-test/suite/parts/t/backup_log_rocksdb.test24
-rw-r--r--sql/backup.cc176
-rw-r--r--sql/backup.h13
-rw-r--r--sql/datadict.cc85
-rw-r--r--sql/datadict.h6
-rw-r--r--sql/ha_partition.cc14
-rw-r--r--sql/ha_partition.h7
-rw-r--r--sql/handler.cc61
-rw-r--r--sql/handler.h15
-rw-r--r--sql/mdl.cc21
-rw-r--r--sql/mysqld.cc8
-rw-r--r--sql/mysqld.h4
-rw-r--r--sql/sql_admin.cc34
-rw-r--r--sql/sql_alter.cc22
-rw-r--r--sql/sql_alter.h14
-rw-r--r--sql/sql_base.cc2
-rw-r--r--sql/sql_class.cc1
-rw-r--r--sql/sql_db.cc28
-rw-r--r--sql/sql_insert.cc58
-rw-r--r--sql/sql_partition.cc28
-rw-r--r--sql/sql_partition.h1
-rw-r--r--sql/sql_partition_admin.cc49
-rw-r--r--sql/sql_plugin.cc3
-rw-r--r--sql/sql_rename.cc9
-rw-r--r--sql/sql_show.cc6
-rw-r--r--sql/sql_table.cc293
-rw-r--r--sql/sql_table.h8
-rw-r--r--sql/sql_trigger.cc11
-rw-r--r--sql/sql_truncate.cc23
-rw-r--r--sql/sql_view.cc18
-rw-r--r--storage/maria/ha_maria.cc1
-rw-r--r--storage/rocksdb/rdb_datadic.cc3
46 files changed, 1841 insertions, 145 deletions
diff --git a/mysql-test/include/print_ddl_log.inc b/mysql-test/include/print_ddl_log.inc
new file mode 100644
index 00000000000..7b09c62231e
--- /dev/null
+++ b/mysql-test/include/print_ddl_log.inc
@@ -0,0 +1,78 @@
+--echo #
+--echo # Reading backup ddl log file
+--echo #
+
+let MYSQLD_DATADIR= `select @@datadir`;
+perl;
+ $datadir= $ENV{'MYSQLD_DATADIR'};
+ $id_count= 0;
+ $tmp_table_count;
+
+ open(FILE, "$datadir/ddl.log") or
+ die("Unable to read log file $datadir/ddl.log: $!\n");
+ while(<FILE>)
+ {
+ chop;
+ if (/([^\t]*)[\t]([^\t]*)[\t]([^\t]*)[\t]([^\t]*)[\t]([^\t]*)[\t]([^\t]*)[\t]([^\t]*)[\t]([^\t]*)[\t]([^\t]*)[\t]([^\t]*)[\t]([^\t]*)[\t]([^\t]*)/)
+ {
+ my $date = $1;
+ my $query = $2;
+ my $storage = $3;
+ my $partitioned = $4;
+ my $db = $5;
+ my $table = $6;
+ my $table_ver = $7;
+ my $new_storage = $8;
+ my $new_partitioned = $9;
+ my $new_db = $10;
+ my $new_table = $11;
+ my $new_table_ver = $12;
+ # Fix table ids
+ $table_id1= "";
+ $table_id2= "";
+ if (!($table_ver eq ""))
+ {
+ $table_id1= "id: $id{$table_ver}";
+ if (!exists($id{$table_ver}))
+ {
+ $id_count++;
+ $table_id1= "id: $id_count";
+ $id{$table_ver}= $id_count;
+ }
+ }
+ if (!($new_table_ver eq ""))
+ {
+ $table_id2= "id: $id{$new_table_ver}";
+ if (!exists($id{$new_table_ver}))
+ {
+ $id_count++;
+ $table_id2= "id: $id_count";
+ $id{$new_table_ver}= $id_count;
+ }
+ }
+ # Fix table names
+ $table_name1= $table;
+ if (substr($table_name1,0,5) eq '@0023')
+ {
+ if (!exists($name{$table_name1}))
+ {
+ $tmp_table_count++;
+ $name{$table_name1}= "#sql" . $tmp_table_count;
+ }
+ $table_name1= $name{$table_name1};
+ }
+ $table_name2= $new_table;
+ if (substr($table_name2,0,5) eq '@0023')
+ {
+ if (!exists($name{$table_name2}))
+ {
+ $tmp_table_count++;
+ $name{$table_name2}= "#sql" . $tmp_table_count;
+ }
+ $table_name2= $name{$table_name2};
+ }
+
+ print "$query,$storage,$partitioned,$db,$table_name1,$table_id1,$new_storage,$new_partitioned,$new_db,$table_name2,$table_id2\n";
+ }
+ }
+EOF
diff --git a/mysql-test/main/backup_lock.result b/mysql-test/main/backup_lock.result
index 96503814d00..e519d3d325a 100644
--- a/mysql-test/main/backup_lock.result
+++ b/mysql-test/main/backup_lock.result
@@ -30,12 +30,14 @@ connection default;
# testing if BACKUP STAGE FLUSH causes deadlocks with ALTER TABLE
#
create table t1 (a int) engine=innodb;
+connection con2;
+backup stage start;
+connection default;
start transaction;
insert into t1 values (1);
connection con1;
alter table t1 add column (j int), algorithm copy;
connection con2;
-backup stage start;
backup stage flush;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
@@ -175,6 +177,23 @@ select * from t1;
a
1
drop table t1;
+#
+# Check if BACKUP STAGE BLOCK_DDL blocks create view
+#
+create table t1 (a int) engine=innodb;
+connection con1;
+backup stage start;
+backup stage block_ddl;
+connection default;
+create view v1 as select * from t1;;
+connection con1;
+select count(*) = 1 from information_schema.processlist;
+count(*) = 1
+0
+backup stage end;
+connection default;
+drop table t1;
+drop view v1;
disconnect con1;
disconnect con2;
#
diff --git a/mysql-test/main/backup_lock.test b/mysql-test/main/backup_lock.test
index 0d4da8cb892..f51b6ecdaad 100644
--- a/mysql-test/main/backup_lock.test
+++ b/mysql-test/main/backup_lock.test
@@ -36,6 +36,10 @@ connection default;
create table t1 (a int) engine=innodb;
+connection con2;
+backup stage start;
+connection default;
+
start transaction;
# Acquires MDL lock
insert into t1 values (1);
@@ -49,7 +53,6 @@ let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for table metadata lock";
--source include/wait_condition.inc
-backup stage start;
backup stage flush;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
#
@@ -227,6 +230,28 @@ connection default;
select * from t1;
drop table t1;
+--echo #
+--echo # Check if BACKUP STAGE BLOCK_DDL blocks create view
+--echo #
+
+create table t1 (a int) engine=innodb;
+connection con1;
+backup stage start;
+backup stage block_ddl;
+connection default;
+--send create view v1 as select * from t1;
+connection con1;
+--sleep 2
+select count(*) = 1 from information_schema.processlist;
+let $wait_condition=
+ select count(*) = 1 from information_schema.processlist
+ where state = "Waiting for backup lock";
+backup stage end;
+connection default;
+--reap # create
+drop table t1;
+drop view v1;
+
#
# End of tests using con1 and con2
#
diff --git a/mysql-test/main/backup_lock_debug.result b/mysql-test/main/backup_lock_debug.result
index 7c7b05901a9..229c32a85f4 100644
--- a/mysql-test/main/backup_lock_debug.result
+++ b/mysql-test/main/backup_lock_debug.result
@@ -33,11 +33,13 @@ SET DEBUG_SYNC= 'RESET';
#
CREATE DATABASE test2;
CREATE TABLE t1(a INT) ENGINE=InnoDB;
+connect con1,localhost,root,,;
+BACKUP STAGE START;
+connection default;
SET DEBUG_SYNC='alter_opened_table SIGNAL ready WAIT_FOR go';
ALTER TABLE t1 RENAME TO test2.t1;
-connect con1,localhost,root,,;
+connection con1;
SET DEBUG_SYNC='now WAIT_FOR ready';
-BACKUP STAGE START;
SET DEBUG_SYNC='mdl_acquire_lock_wait SIGNAL ready1';
BACKUP STAGE BLOCK_DDL;
connect con2,localhost,root,,;
diff --git a/mysql-test/main/backup_lock_debug.test b/mysql-test/main/backup_lock_debug.test
index 80e7cf9e181..37d70b04e0d 100644
--- a/mysql-test/main/backup_lock_debug.test
+++ b/mysql-test/main/backup_lock_debug.test
@@ -49,12 +49,15 @@ SET DEBUG_SYNC= 'RESET';
CREATE DATABASE test2;
CREATE TABLE t1(a INT) ENGINE=InnoDB;
+connect (con1,localhost,root,,);
+BACKUP STAGE START;
+
+--connection default
SET DEBUG_SYNC='alter_opened_table SIGNAL ready WAIT_FOR go';
send ALTER TABLE t1 RENAME TO test2.t1;
-connect (con1,localhost,root,,);
+--connection con1
SET DEBUG_SYNC='now WAIT_FOR ready';
-BACKUP STAGE START;
SET DEBUG_SYNC='mdl_acquire_lock_wait SIGNAL ready1';
send BACKUP STAGE BLOCK_DDL;
diff --git a/mysql-test/main/backup_log.inc b/mysql-test/main/backup_log.inc
new file mode 100644
index 00000000000..f553a3b9527
--- /dev/null
+++ b/mysql-test/main/backup_log.inc
@@ -0,0 +1,155 @@
+# This file is used for common DDL log test for both partiotioned
+# and non-partitioned tables.
+# Parameters:
+# $part_int - partition definition for int field, must be empty for
+# non-partitioned testing
+# $part_date - partition definition for date field, must be empty for
+# non-partitioned testing
+
+--echo #
+--echo # Testing with normal tables
+--echo #
+
+eval create table t1 (a int) engine=myisam $part_int;
+insert into t1 values (1),(2);
+alter table t1 add column b int;
+alter table t1 rename as t2;
+rename table t2 to t1;
+truncate table t1;
+repair table t1;
+optimize table t1;
+drop table t1;
+
+eval create table t1_innodb (a int) engine=innodb $part_int;
+insert into t1_innodb values (1),(2);
+alter table t1_innodb add column b int;
+alter table t1_innodb rename as t2_innodb;
+rename table t2_innodb to t1_innodb;
+truncate table t1_innodb;
+repair table t1_innodb;
+optimize table t1_innodb;
+drop table t1_innodb;
+
+--echo #
+--echo # Testing with temporary tables (should not be logged)
+--echo #
+
+create temporary table tmp_t10 (a int) engine=myisam;
+alter table tmp_t10 add column b int;
+alter table tmp_t10 rename as tmp_t11;
+rename table tmp_t11 to tmp_t10;
+truncate table tmp_t10;
+drop table tmp_t10;
+
+--echo #
+--echo # Testing with mix of normal and temporary tables
+--echo #
+
+create temporary table tmp_t20 (a int);
+eval create table t20 (a int) $part_int;
+drop table tmp_t20,t20;
+
+create temporary table tmp_t21 (a int);
+eval create table t21 (a int) $part_int;
+drop temporary table if exists tmp_t21,t21;
+drop table if exists tmp_t21,t21;
+
+--echo #
+--echo # Testing create select
+--echo #
+
+eval create table t30 (a int) $part_int;
+insert into t30 values (1),(1);
+eval create table t31 (a int primary key) $part_int select * from t30 limit 1;
+create or replace table t31 select * from t30 limit 1;
+create or replace temporary table t30_dup select * from t30 limit 1;
+--error ER_DUP_ENTRY
+eval create or replace table t31 (a int primary key) $part_int select * from t30;
+eval create table t32 (a int) $part_int;
+drop table if exists t30,t31,t32,tmp_t30;
+
+--echo #
+--echo # Testing create LIKE
+--echo #
+eval create table t40 (a int) engine=myisam $part_int;
+eval create table t41 (a int, b int) engine=innodb $part_int;
+create table t42 like t40;
+if (!$part_int) {
+create temporary table t43_tmp like t40;
+}
+create or replace table t42 like t41;
+show create table t42;
+drop table t40, t41, t42;
+
+--echo #
+--echo # Testing rename
+--echo #
+
+eval create table t50 (a int) $part_int;
+eval create table t51 (a int, b int) $part_int;
+rename table t50 to t52, t51 to t53;
+rename table t52 to tmp, t53 to t52, tmp to t53;
+drop table t52,t53;
+
+--echo #
+--echo # Testing enable/disable keys
+--echo #
+
+eval CREATE TABLE t60 (a int(10), index(a) ) ENGINE=Aria $part_int;
+INSERT INTO t60 VALUES(1),(2),(3);
+ALTER TABLE t60 DISABLE KEYS;
+INSERT INTO t60 VALUES(4),(5),(6);
+ALTER TABLE t60 ENABLE KEYS;
+DROP TABLE t60;
+
+CREATE TEMPORARY TABLE t61 (i int(10), index(i) ) ENGINE=Aria;
+INSERT INTO t61 VALUES(1),(2),(3);
+ALTER TABLE t61 DISABLE KEYS;
+DROP TABLE t61;
+
+--echo #
+--echo # Testing load data
+--echo #
+
+eval create table t70 (a date, b date, c date not null, d date) engine=aria $part_date;
+--disable_warnings
+load data infile '../../std_data/loaddata1.dat' ignore into table t70 fields terminated by ',';
+load data infile '../../std_data/loaddata1.dat' ignore into table t70 fields terminated by ',';
+truncate table t70;
+lock table t70 write;
+load data infile '../../std_data/loaddata1.dat' ignore into table t70 fields terminated by ',';
+load data infile '../../std_data/loaddata1.dat' ignore into table t70 fields terminated by ',';
+unlock tables;
+--enable_warnings
+
+eval create table t71 (a date, b date, c date not null, d date) engine=aria $part_date;
+lock tables t71 write, t70 read;
+insert into t71 select * from t70;
+unlock tables;
+drop table t70,t71;
+
+--echo #
+--echo # Testing strange table names
+--echo #
+
+eval create table `t 1` (a int) $part_int;
+drop table `t 1`;
+
+--echo #
+--echo # Testing views and triggers
+--echo #
+
+eval create table t80 (a int, b int) engine=myisam $part_int;
+create view v1 as select * from t80;
+create trigger trg before insert on t80 for each row set @b:=1;
+drop trigger trg;
+drop view v1;
+drop table t80;
+
+--echo #
+--echo # Testing alter to a new storage engine
+--echo #
+
+eval create table t85 (a int primary key, b int) engine=myisam $part_int;
+alter table t85 engine=innodb;
+drop table t85;
diff --git a/mysql-test/main/backup_log.result b/mysql-test/main/backup_log.result
new file mode 100644
index 00000000000..94590a220d4
--- /dev/null
+++ b/mysql-test/main/backup_log.result
@@ -0,0 +1,241 @@
+CREATE TABLE t_exists (a INT);
+CREATE TABLE t_exists_template (a INT);
+connect con1,localhost,root,,;
+BACKUP STAGE START;
+connection default;
+#
+# Testing with normal tables
+#
+create table t1 (a int) engine=myisam ;
+insert into t1 values (1),(2);
+alter table t1 add column b int;
+alter table t1 rename as t2;
+rename table t2 to t1;
+truncate table t1;
+repair table t1;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+drop table t1;
+create table t1_innodb (a int) engine=innodb ;
+insert into t1_innodb values (1),(2);
+alter table t1_innodb add column b int;
+alter table t1_innodb rename as t2_innodb;
+rename table t2_innodb to t1_innodb;
+truncate table t1_innodb;
+repair table t1_innodb;
+Table Op Msg_type Msg_text
+test.t1_innodb repair note The storage engine for the table doesn't support repair
+optimize table t1_innodb;
+Table Op Msg_type Msg_text
+test.t1_innodb optimize note Table does not support optimize, doing recreate + analyze instead
+test.t1_innodb optimize status OK
+drop table t1_innodb;
+#
+# Testing with temporary tables (should not be logged)
+#
+create temporary table tmp_t10 (a int) engine=myisam;
+alter table tmp_t10 add column b int;
+alter table tmp_t10 rename as tmp_t11;
+rename table tmp_t11 to tmp_t10;
+truncate table tmp_t10;
+drop table tmp_t10;
+#
+# Testing with mix of normal and temporary tables
+#
+create temporary table tmp_t20 (a int);
+create table t20 (a int) ;
+drop table tmp_t20,t20;
+create temporary table tmp_t21 (a int);
+create table t21 (a int) ;
+drop temporary table if exists tmp_t21,t21;
+Warnings:
+Note 1051 Unknown table 'test.t21'
+drop table if exists tmp_t21,t21;
+Warnings:
+Note 1051 Unknown table 'test.tmp_t21'
+#
+# Testing create select
+#
+create table t30 (a int) ;
+insert into t30 values (1),(1);
+create table t31 (a int primary key) select * from t30 limit 1;
+create or replace table t31 select * from t30 limit 1;
+create or replace temporary table t30_dup select * from t30 limit 1;
+create or replace table t31 (a int primary key) select * from t30;
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+create table t32 (a int) ;
+drop table if exists t30,t31,t32,tmp_t30;
+Warnings:
+Note 1051 Unknown table 'test.t31,test.tmp_t30'
+#
+# Testing create LIKE
+#
+create table t40 (a int) engine=myisam ;
+create table t41 (a int, b int) engine=innodb ;
+create table t42 like t40;
+create temporary table t43_tmp like t40;
+create or replace table t42 like t41;
+show create table t42;
+Table Create Table
+t42 CREATE TABLE `t42` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t40, t41, t42;
+#
+# Testing rename
+#
+create table t50 (a int) ;
+create table t51 (a int, b int) ;
+rename table t50 to t52, t51 to t53;
+rename table t52 to tmp, t53 to t52, tmp to t53;
+drop table t52,t53;
+#
+# Testing enable/disable keys
+#
+CREATE TABLE t60 (a int(10), index(a) ) ENGINE=Aria ;
+INSERT INTO t60 VALUES(1),(2),(3);
+ALTER TABLE t60 DISABLE KEYS;
+INSERT INTO t60 VALUES(4),(5),(6);
+ALTER TABLE t60 ENABLE KEYS;
+DROP TABLE t60;
+CREATE TEMPORARY TABLE t61 (i int(10), index(i) ) ENGINE=Aria;
+INSERT INTO t61 VALUES(1),(2),(3);
+ALTER TABLE t61 DISABLE KEYS;
+DROP TABLE t61;
+#
+# Testing load data
+#
+create table t70 (a date, b date, c date not null, d date) engine=aria ;
+load data infile '../../std_data/loaddata1.dat' ignore into table t70 fields terminated by ',';
+load data infile '../../std_data/loaddata1.dat' ignore into table t70 fields terminated by ',';
+truncate table t70;
+lock table t70 write;
+load data infile '../../std_data/loaddata1.dat' ignore into table t70 fields terminated by ',';
+load data infile '../../std_data/loaddata1.dat' ignore into table t70 fields terminated by ',';
+unlock tables;
+create table t71 (a date, b date, c date not null, d date) engine=aria ;
+lock tables t71 write, t70 read;
+insert into t71 select * from t70;
+unlock tables;
+drop table t70,t71;
+#
+# Testing strange table names
+#
+create table `t 1` (a int) ;
+drop table `t 1`;
+#
+# Testing views and triggers
+#
+create table t80 (a int, b int) engine=myisam ;
+create view v1 as select * from t80;
+create trigger trg before insert on t80 for each row set @b:=1;
+drop trigger trg;
+drop view v1;
+drop table t80;
+#
+# Testing alter to a new storage engine
+#
+create table t85 (a int primary key, b int) engine=myisam ;
+alter table t85 engine=innodb;
+drop table t85;
+#
+# Testing create/drop/alter database
+#
+create database mysqltest;
+create table mysqltest.t90 (a int primary key, b int) engine=myisam;
+create table mysqltest.t91 (a int primary key, b int) engine=innodb;
+alter database mysqltest character set utf8;
+drop database mysqltest;
+#
+# MENT-222 bug testing
+#
+CREATE TABLE IF NOT EXISTS t_exists LIKE t_exists_template;
+Warnings:
+Note 1050 Table 't_exists' already exists
+#
+# Reading backup ddl log file
+#
+CREATE,MyISAM,0,test,t1,id: 1,,0,,,
+ALTER,MyISAM,0,test,t1,id: 1,MyISAM,0,test,t1,id: 2
+RENAME,MyISAM,0,test,t1,id: 2,MyISAM,0,test,t2,id: 2
+RENAME,MyISAM,0,test,t2,id: 2,MyISAM,0,test,t1,id: 2
+repair,MyISAM,0,test,t1,id: 2,,0,,,
+optimize,MyISAM,0,test,t1,id: 2,,0,,,
+DROP,MyISAM,0,test,t1,id: 2,,0,,,
+CREATE,InnoDB,0,test,t1_innodb,id: 3,,0,,,
+ALTER,InnoDB,0,test,t1_innodb,id: 3,InnoDB,0,test,t1_innodb,id: 4
+RENAME,InnoDB,0,test,t1_innodb,id: 4,InnoDB,0,test,t2_innodb,id: 4
+RENAME,InnoDB,0,test,t2_innodb,id: 4,InnoDB,0,test,t1_innodb,id: 4
+TRUNCATE,InnoDB,0,test,t1_innodb,id: 4,,0,,,
+repair,InnoDB,0,test,t1_innodb,id: 4,,0,,,
+ALTER,InnoDB,0,test,t1_innodb,id: 4,InnoDB,0,test,t1_innodb,id: 5
+DROP,InnoDB,0,test,t1_innodb,id: 5,,0,,,
+CREATE,MyISAM,0,test,t20,id: 6,,0,,,
+DROP,MyISAM,0,test,t20,id: 6,,0,,,
+CREATE,MyISAM,0,test,t21,id: 7,,0,,,
+DROP,MyISAM,0,test,t21,id: 7,,0,,,
+CREATE,MyISAM,0,test,t30,id: 8,,0,,,
+CREATE,MyISAM,0,test,t31,id: 9,,0,,,
+DROP,MyISAM,0,test,t31,id: 9,,0,,,
+CREATE,MyISAM,0,test,t31,id: 10,,0,,,
+DROP,MyISAM,0,test,t31,id: 10,,0,,,
+DROP_AFTER_CREATE,MyISAM,0,test,t31,id: 11,,0,,,
+CREATE,MyISAM,0,test,t32,id: 12,,0,,,
+DROP,MyISAM,0,test,t30,id: 8,,0,,,
+DROP,MyISAM,0,test,t32,id: 12,,0,,,
+CREATE,MyISAM,0,test,t40,id: 13,,0,,,
+CREATE,InnoDB,0,test,t41,id: 14,,0,,,
+CREATE,MyISAM,0,test,t42,id: 15,,0,,,
+DROP,MyISAM,0,test,t42,id: 15,,0,,,
+CREATE,InnoDB,0,test,t42,id: 16,,0,,,
+DROP,MyISAM,0,test,t40,id: 13,,0,,,
+DROP,InnoDB,0,test,t41,id: 14,,0,,,
+DROP,InnoDB,0,test,t42,id: 16,,0,,,
+CREATE,MyISAM,0,test,t50,id: 17,,0,,,
+CREATE,MyISAM,0,test,t51,id: 18,,0,,,
+RENAME,MyISAM,0,test,t50,id: 17,MyISAM,0,test,t52,id: 17
+RENAME,MyISAM,0,test,t51,id: 18,MyISAM,0,test,t53,id: 18
+RENAME,MyISAM,0,test,t52,id: 17,MyISAM,0,test,tmp,id: 17
+RENAME,MyISAM,0,test,t53,id: 18,MyISAM,0,test,t52,id: 18
+RENAME,MyISAM,0,test,tmp,id: 17,MyISAM,0,test,t53,id: 17
+DROP,MyISAM,0,test,t52,id: 18,,0,,,
+DROP,MyISAM,0,test,t53,id: 17,,0,,,
+CREATE,Aria,0,test,t60,id: 19,,0,,,
+CHANGE_INDEX,Aria,0,test,t60,id: 19,,0,,,
+CHANGE_INDEX,Aria,0,test,t60,id: 19,,0,,,
+DROP,Aria,0,test,t60,id: 19,,0,,,
+CREATE,Aria,0,test,t70,id: 20,,0,,,
+BULK_INSERT,Aria,0,test,t70,id: 20,,0,,,
+BULK_INSERT,Aria,0,test,t70,id: 20,,0,,,
+CREATE,Aria,0,test,t71,id: 21,,0,,,
+BULK_INSERT,Aria,0,test,t71,id: 21,,0,,,
+DROP,Aria,0,test,t70,id: 20,,0,,,
+DROP,Aria,0,test,t71,id: 21,,0,,,
+CREATE,MyISAM,0,test,t@00201,id: 22,,0,,,
+DROP,MyISAM,0,test,t@00201,id: 22,,0,,,
+CREATE,MyISAM,0,test,t80,id: 23,,0,,,
+CREATE,VIEW,0,test,v1,,,0,,,
+CREATE,TRIGGER,0,test,trg,,,0,,,
+DROP,TRIGGER,0,test,trg,,,0,,,
+DROP,VIEW,0,test,v1,,,0,,,
+DROP,MyISAM,0,test,t80,id: 23,,0,,,
+CREATE,MyISAM,0,test,t85,id: 24,,0,,,
+ALTER,MyISAM,0,test,t85,id: 24,InnoDB,0,test,t85,id: 25
+DROP,InnoDB,0,test,t85,id: 25,,0,,,
+CREATE,DATABASE,0,mysqltest,,,,0,,,
+CREATE,MyISAM,0,mysqltest,t90,id: 26,,0,,,
+CREATE,InnoDB,0,mysqltest,t91,id: 27,,0,,,
+ALTER,DATABASE,0,mysqltest,,,,0,,,
+DROP,MyISAM,0,mysqltest,t90,id: 26,,0,,,
+DROP,InnoDB,0,mysqltest,t91,id: 27,,0,,,
+DROP,DATABASE,0,mysqltest,,,,0,,,
+#
+# Cleanup
+#
+DROP TABLE t_exists;
+DROP TABLE t_exists_template;
+disconnect con1;
diff --git a/mysql-test/main/backup_log.test b/mysql-test/main/backup_log.test
new file mode 100644
index 00000000000..ee34484e92b
--- /dev/null
+++ b/mysql-test/main/backup_log.test
@@ -0,0 +1,39 @@
+# Testing of logging of ddl's under backup stages
+
+--source include/have_innodb.inc
+--source include/not_embedded.inc
+
+CREATE TABLE t_exists (a INT);
+CREATE TABLE t_exists_template (a INT);
+
+connect (con1,localhost,root,,);
+BACKUP STAGE START;
+connection default;
+
+--let $part_int=
+--let $part_date=
+--source backup_log.inc
+
+--echo #
+--echo # Testing create/drop/alter database
+--echo #
+
+create database mysqltest;
+create table mysqltest.t90 (a int primary key, b int) engine=myisam;
+create table mysqltest.t91 (a int primary key, b int) engine=innodb;
+alter database mysqltest character set utf8;
+drop database mysqltest;
+
+--echo #
+--echo # MENT-222 bug testing
+--echo #
+CREATE TABLE IF NOT EXISTS t_exists LIKE t_exists_template;
+
+--source include/print_ddl_log.inc
+
+--echo #
+--echo # Cleanup
+--echo #
+DROP TABLE t_exists;
+DROP TABLE t_exists_template;
+disconnect con1;
diff --git a/mysql-test/main/backup_stages.result b/mysql-test/main/backup_stages.result
index 4704a4b6bd1..823e5d7e462 100644
--- a/mysql-test/main/backup_stages.result
+++ b/mysql-test/main/backup_stages.result
@@ -17,12 +17,12 @@ FROM information_schema.processlist WHERE id = @con1_id;
ID USER COMMAND STATE INFO STAGE MAX_STAGE INFO_BINARY
<con1_id> root Query Waiting for backup lock BACKUP STAGE START 0 0 BACKUP STAGE START
BACKUP STAGE END;
-SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
-LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
-MDL_BACKUP_START Backup lock
connection con1;
# The connection default has removed the backup lock.
# And so the current connection con1 can reap for its BACKUP STAGE START
+SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
+LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
+MDL_BACKUP_START Backup lock
connect con2,localhost,root,,;
# The connection con2 cannot continue the work of con1 by setting the
# next BACKUP STAGE FLUSH.
diff --git a/mysql-test/main/backup_stages.test b/mysql-test/main/backup_stages.test
index e8cc5f7a7b9..77d410b6caf 100644
--- a/mysql-test/main/backup_stages.test
+++ b/mysql-test/main/backup_stages.test
@@ -50,13 +50,14 @@ FROM information_schema.processlist WHERE id = @con1_id;
# con1 uses @@global.lock_wait_timeout
BACKUP STAGE END;
-SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
--connection con1
--echo # The connection default has removed the backup lock.
--echo # And so the current connection con1 can reap for its BACKUP STAGE START
--reap
+SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
+
# con2, root high privileged user
--connect(con2,localhost,root,,)
let $con2_id= `SELECT CONNECTION_ID()`;
diff --git a/mysql-test/suite/parts/r/backup_log.result b/mysql-test/suite/parts/r/backup_log.result
new file mode 100644
index 00000000000..3a220491027
--- /dev/null
+++ b/mysql-test/suite/parts/r/backup_log.result
@@ -0,0 +1,278 @@
+connect con1,localhost,root,,;
+BACKUP STAGE START;
+connection default;
+#
+# Testing with normal tables
+#
+create table t1 (a int) engine=myisam PARTITION BY HASH(a) PARTITIONS 2;
+insert into t1 values (1),(2);
+alter table t1 add column b int;
+alter table t1 rename as t2;
+rename table t2 to t1;
+truncate table t1;
+repair table t1;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+drop table t1;
+create table t1_innodb (a int) engine=innodb PARTITION BY HASH(a) PARTITIONS 2;
+insert into t1_innodb values (1),(2);
+alter table t1_innodb add column b int;
+alter table t1_innodb rename as t2_innodb;
+rename table t2_innodb to t1_innodb;
+truncate table t1_innodb;
+repair table t1_innodb;
+Table Op Msg_type Msg_text
+test.t1_innodb repair status OK
+optimize table t1_innodb;
+Table Op Msg_type Msg_text
+test.t1_innodb optimize note Table does not support optimize, doing recreate + analyze instead
+test.t1_innodb optimize status OK
+drop table t1_innodb;
+#
+# Testing with temporary tables (should not be logged)
+#
+create temporary table tmp_t10 (a int) engine=myisam;
+alter table tmp_t10 add column b int;
+alter table tmp_t10 rename as tmp_t11;
+rename table tmp_t11 to tmp_t10;
+truncate table tmp_t10;
+drop table tmp_t10;
+#
+# Testing with mix of normal and temporary tables
+#
+create temporary table tmp_t20 (a int);
+create table t20 (a int) PARTITION BY HASH(a) PARTITIONS 2;
+drop table tmp_t20,t20;
+create temporary table tmp_t21 (a int);
+create table t21 (a int) PARTITION BY HASH(a) PARTITIONS 2;
+drop temporary table if exists tmp_t21,t21;
+Warnings:
+Note 1051 Unknown table 'test.t21'
+drop table if exists tmp_t21,t21;
+Warnings:
+Note 1051 Unknown table 'test.tmp_t21'
+#
+# Testing create select
+#
+create table t30 (a int) PARTITION BY HASH(a) PARTITIONS 2;
+insert into t30 values (1),(1);
+create table t31 (a int primary key) PARTITION BY HASH(a) PARTITIONS 2 select * from t30 limit 1;
+create or replace table t31 select * from t30 limit 1;
+create or replace temporary table t30_dup select * from t30 limit 1;
+create or replace table t31 (a int primary key) PARTITION BY HASH(a) PARTITIONS 2 select * from t30;
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+create table t32 (a int) PARTITION BY HASH(a) PARTITIONS 2;
+drop table if exists t30,t31,t32,tmp_t30;
+Warnings:
+Note 1051 Unknown table 'test.t31,test.tmp_t30'
+#
+# Testing create LIKE
+#
+create table t40 (a int) engine=myisam PARTITION BY HASH(a) PARTITIONS 2;
+create table t41 (a int, b int) engine=innodb PARTITION BY HASH(a) PARTITIONS 2;
+create table t42 like t40;
+create or replace table t42 like t41;
+show create table t42;
+Table Create Table
+t42 CREATE TABLE `t42` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+ PARTITION BY HASH (`a`)
+PARTITIONS 2
+drop table t40, t41, t42;
+#
+# Testing rename
+#
+create table t50 (a int) PARTITION BY HASH(a) PARTITIONS 2;
+create table t51 (a int, b int) PARTITION BY HASH(a) PARTITIONS 2;
+rename table t50 to t52, t51 to t53;
+rename table t52 to tmp, t53 to t52, tmp to t53;
+drop table t52,t53;
+#
+# Testing enable/disable keys
+#
+CREATE TABLE t60 (a int(10), index(a) ) ENGINE=Aria PARTITION BY HASH(a) PARTITIONS 2;
+INSERT INTO t60 VALUES(1),(2),(3);
+ALTER TABLE t60 DISABLE KEYS;
+INSERT INTO t60 VALUES(4),(5),(6);
+ALTER TABLE t60 ENABLE KEYS;
+DROP TABLE t60;
+CREATE TEMPORARY TABLE t61 (i int(10), index(i) ) ENGINE=Aria;
+INSERT INTO t61 VALUES(1),(2),(3);
+ALTER TABLE t61 DISABLE KEYS;
+DROP TABLE t61;
+#
+# Testing load data
+#
+create table t70 (a date, b date, c date not null, d date) engine=aria PARTITION BY HASH(YEAR(a)) PARTITIONS 2;
+load data infile '../../std_data/loaddata1.dat' ignore into table t70 fields terminated by ',';
+load data infile '../../std_data/loaddata1.dat' ignore into table t70 fields terminated by ',';
+truncate table t70;
+lock table t70 write;
+load data infile '../../std_data/loaddata1.dat' ignore into table t70 fields terminated by ',';
+load data infile '../../std_data/loaddata1.dat' ignore into table t70 fields terminated by ',';
+unlock tables;
+create table t71 (a date, b date, c date not null, d date) engine=aria PARTITION BY HASH(YEAR(a)) PARTITIONS 2;
+lock tables t71 write, t70 read;
+insert into t71 select * from t70;
+unlock tables;
+drop table t70,t71;
+#
+# Testing strange table names
+#
+create table `t 1` (a int) PARTITION BY HASH(a) PARTITIONS 2;
+drop table `t 1`;
+#
+# Testing views and triggers
+#
+create table t80 (a int, b int) engine=myisam PARTITION BY HASH(a) PARTITIONS 2;
+create view v1 as select * from t80;
+create trigger trg before insert on t80 for each row set @b:=1;
+drop trigger trg;
+drop view v1;
+drop table t80;
+#
+# Testing alter to a new storage engine
+#
+create table t85 (a int primary key, b int) engine=myisam PARTITION BY HASH(a) PARTITIONS 2;
+alter table t85 engine=innodb;
+drop table t85;
+#
+# Testing backup ddl log for partitioned tables
+#
+CREATE TABLE t200(a INT, b INT) ENGINE ARIA TRANSACTIONAL = 1 PAGE_CHECKSUM = 1;
+INSERT INTO t200 VALUES (5, 5), (15, 15), (25, 25);
+ALTER TABLE t200 PARTITION BY RANGE( a ) (
+PARTITION p0 VALUES LESS THAN (10),
+PARTITION p1 VALUES LESS THAN (20),
+PARTITION p2 VALUES LESS THAN (30)
+);
+CREATE TABLE t210(a INT, b INT) ENGINE ARIA TRANSACTIONAL = 1 PAGE_CHECKSUM = 1;
+#TODO: echange partitions have not logged yet
+ALTER TABLE t200 EXCHANGE PARTITION p2 WITH TABLE t210;
+ALTER TABLE t200 DROP PARTITION p0;
+ALTER TABLE t200 ADD PARTITION (PARTITION p3 VALUES LESS THAN (40));
+ALTER TABLE t200
+REORGANIZE PARTITION p3 INTO (
+PARTITION n0 VALUES LESS THAN (35),
+PARTITION n1 VALUES LESS THAN (45)
+);
+ALTER TABLE t200 PARTITION BY KEY(a) PARTITIONS 2;
+ALTER TABLE t200 PARTITION BY HASH(a) PARTITIONS 8;
+ALTER TABLE t200 COALESCE PARTITION 4;
+ALTER TABLE t200
+PARTITION BY RANGE (b)
+SUBPARTITION BY KEY (a)
+SUBPARTITIONS 2 (
+PARTITION p0 VALUES LESS THAN (10),
+PARTITION p1 VALUES LESS THAN (20),
+PARTITION p2 VALUES LESS THAN (30),
+PARTITION p3 VALUES LESS THAN (MAXVALUE)
+);
+ALTER TABLE t200 REMOVE PARTITIONING;
+DROP TABLE t200, t210;
+# Test for the case when TDC contains TABLE_SHARE object for the
+# certain table, but the table is not opened
+CREATE TABLE t220(a INT) ENGINE ARIA PARTITION BY HASH(a) PARTITIONS 2;
+SELECT VERSION FROM INFORMATION_SCHEMA.tables WHERE
+TABLE_SCHEMA = 'test' AND TABLE_NAME = 't220';
+DROP TABLE t220;
+#
+# Reading backup ddl log file
+#
+CREATE,MyISAM,1,test,t1,id: 1,,0,,,
+ALTER,MyISAM,1,test,t1,id: 1,MyISAM,1,test,t1,id: 2
+RENAME,MyISAM,1,test,t1,id: 2,MyISAM,1,test,t2,id: 2
+RENAME,MyISAM,1,test,t2,id: 2,MyISAM,1,test,t1,id: 2
+TRUNCATE,MyISAM,1,test,t1,id: 2,,0,,,
+repair,MyISAM,1,test,t1,id: 2,,0,,,
+optimize,MyISAM,1,test,t1,id: 2,,0,,,
+DROP,MyISAM,1,test,t1,id: 2,,0,,,
+CREATE,InnoDB,1,test,t1_innodb,id: 3,,0,,,
+ALTER,InnoDB,1,test,t1_innodb,id: 3,InnoDB,1,test,t1_innodb,id: 4
+RENAME,InnoDB,1,test,t1_innodb,id: 4,InnoDB,1,test,t2_innodb,id: 4
+RENAME,InnoDB,1,test,t2_innodb,id: 4,InnoDB,1,test,t1_innodb,id: 4
+TRUNCATE,InnoDB,1,test,t1_innodb,id: 4,,0,,,
+repair,InnoDB,1,test,t1_innodb,id: 4,,0,,,
+ALTER,InnoDB,1,test,t1_innodb,id: 4,InnoDB,1,test,t1_innodb,id: 5
+DROP,InnoDB,1,test,t1_innodb,id: 5,,0,,,
+CREATE,MyISAM,1,test,t20,id: 6,,0,,,
+DROP,MyISAM,1,test,t20,id: 6,,0,,,
+CREATE,MyISAM,1,test,t21,id: 7,,0,,,
+DROP,MyISAM,1,test,t21,id: 7,,0,,,
+CREATE,MyISAM,1,test,t30,id: 8,,0,,,
+CREATE,MyISAM,1,test,t31,id: 9,,0,,,
+DROP,MyISAM,1,test,t31,id: 9,,0,,,
+CREATE,MyISAM,0,test,t31,id: 10,,0,,,
+DROP,MyISAM,0,test,t31,id: 10,,0,,,
+DROP_AFTER_CREATE,MyISAM,1,test,t31,id: 11,,0,,,
+CREATE,MyISAM,1,test,t32,id: 12,,0,,,
+DROP,MyISAM,1,test,t30,id: 8,,0,,,
+DROP,MyISAM,1,test,t32,id: 12,,0,,,
+CREATE,MyISAM,1,test,t40,id: 13,,0,,,
+CREATE,InnoDB,1,test,t41,id: 14,,0,,,
+CREATE,partition,0,test,t42,id: 15,,0,,,
+DROP,MyISAM,1,test,t42,id: 15,,0,,,
+CREATE,partition,0,test,t42,id: 16,,0,,,
+DROP,MyISAM,1,test,t40,id: 13,,0,,,
+DROP,InnoDB,1,test,t41,id: 14,,0,,,
+DROP,InnoDB,1,test,t42,id: 16,,0,,,
+CREATE,MyISAM,1,test,t50,id: 17,,0,,,
+CREATE,MyISAM,1,test,t51,id: 18,,0,,,
+RENAME,MyISAM,1,test,t50,id: 17,MyISAM,1,test,t52,id: 17
+RENAME,MyISAM,1,test,t51,id: 18,MyISAM,1,test,t53,id: 18
+RENAME,MyISAM,1,test,t52,id: 17,MyISAM,1,test,tmp,id: 17
+RENAME,MyISAM,1,test,t53,id: 18,MyISAM,1,test,t52,id: 18
+RENAME,MyISAM,1,test,tmp,id: 17,MyISAM,1,test,t53,id: 17
+DROP,MyISAM,1,test,t52,id: 18,,0,,,
+DROP,MyISAM,1,test,t53,id: 17,,0,,,
+CREATE,Aria,1,test,t60,id: 19,,0,,,
+CHANGE_INDEX,Aria,1,test,t60,id: 19,,0,,,
+CHANGE_INDEX,Aria,1,test,t60,id: 19,,0,,,
+DROP,Aria,1,test,t60,id: 19,,0,,,
+CREATE,Aria,1,test,t70,id: 20,,0,,,
+BULK_INSERT,Aria,1,test,t70,id: 20,,0,,,
+BULK_INSERT,Aria,1,test,t70,id: 20,,0,,,
+TRUNCATE,Aria,1,test,t70,id: 20,,0,,,
+BULK_INSERT,Aria,1,test,t70,id: 20,,0,,,
+BULK_INSERT,Aria,1,test,t70,id: 20,,0,,,
+CREATE,Aria,1,test,t71,id: 21,,0,,,
+BULK_INSERT,Aria,1,test,t71,id: 21,,0,,,
+BULK_INSERT,Aria,1,test,t71,id: 21,,0,,,
+DROP,Aria,1,test,t70,id: 20,,0,,,
+DROP,Aria,1,test,t71,id: 21,,0,,,
+CREATE,MyISAM,1,test,t@00201,id: 22,,0,,,
+DROP,MyISAM,1,test,t@00201,id: 22,,0,,,
+CREATE,MyISAM,1,test,t80,id: 23,,0,,,
+CREATE,VIEW,0,test,v1,,,0,,,
+CREATE,TRIGGER,0,test,trg,,,0,,,
+DROP,TRIGGER,0,test,trg,,,0,,,
+DROP,VIEW,0,test,v1,,,0,,,
+DROP,MyISAM,1,test,t80,id: 23,,0,,,
+CREATE,MyISAM,1,test,t85,id: 24,,0,,,
+ALTER,MyISAM,1,test,t85,id: 24,InnoDB,1,test,t85,id: 25
+DROP,InnoDB,1,test,t85,id: 25,,0,,,
+CREATE,Aria,0,test,t200,id: 26,,0,,,
+ALTER,Aria,0,test,t200,id: 26,Aria,1,test,t200,id: 27
+CREATE,Aria,0,test,t210,id: 28,,0,,,
+EXCHANGE_PARTITION,Aria,1,test,t200,id: 27,Aria,0,test,t210,id: 28
+ALTER,Aria,1,test,t200,id: 27,Aria,1,test,t200,id: 29
+ALTER,Aria,1,test,t200,id: 29,Aria,1,test,t200,id: 30
+ALTER,Aria,1,test,t200,id: 30,Aria,1,test,t200,id: 31
+ALTER,Aria,1,test,t200,id: 31,Aria,1,test,t200,id: 32
+ALTER,Aria,1,test,t200,id: 32,Aria,1,test,t200,id: 33
+ALTER,Aria,1,test,t200,id: 33,Aria,1,test,t200,id: 34
+ALTER,Aria,1,test,t200,id: 34,Aria,1,test,t200,id: 35
+ALTER,Aria,1,test,t200,id: 35,Aria,0,test,t200,id: 36
+DROP,Aria,0,test,t200,id: 36,,0,,,
+DROP,Aria,0,test,t210,id: 28,,0,,,
+CREATE,Aria,1,test,t220,id: 37,,0,,,
+DROP,Aria,1,test,t220,id: 37,,0,,,
+#
+# Cleanup
+#
+disconnect con1;
diff --git a/mysql-test/suite/parts/r/backup_log_rocksdb.result b/mysql-test/suite/parts/r/backup_log_rocksdb.result
new file mode 100644
index 00000000000..3fd0adfe8b3
--- /dev/null
+++ b/mysql-test/suite/parts/r/backup_log_rocksdb.result
@@ -0,0 +1,15 @@
+connect con1,localhost,root,,;
+BACKUP STAGE START;
+connection default;
+# Test partition engine read from .frm
+CREATE TABLE t220 (a INT) ENGINE ROCKSDB PARTITION BY KEY(a) PARTITIONS 2;
+DROP TABLE t220;
+#
+# Reading backup ddl log file
+#
+CREATE,ROCKSDB,1,test,t220,id: 1,,0,,,
+DROP,ROCKSDB,1,test,t220,id: 1,,0,,,
+#
+# Cleanup
+#
+disconnect con1;
diff --git a/mysql-test/suite/parts/t/backup_log.test b/mysql-test/suite/parts/t/backup_log.test
new file mode 100644
index 00000000000..50e3cadd192
--- /dev/null
+++ b/mysql-test/suite/parts/t/backup_log.test
@@ -0,0 +1,63 @@
+--source include/have_partition.inc
+--source include/have_innodb.inc
+--source include/not_embedded.inc
+
+connect (con1,localhost,root,,);
+BACKUP STAGE START;
+connection default;
+
+--let $part_int=PARTITION BY HASH(a) PARTITIONS 2
+--let $part_date=PARTITION BY HASH(YEAR(a)) PARTITIONS 2
+--source main/backup_log.inc
+
+--echo #
+--echo # Testing backup ddl log for partitioned tables
+--echo #
+
+CREATE TABLE t200(a INT, b INT) ENGINE ARIA TRANSACTIONAL = 1 PAGE_CHECKSUM = 1;
+INSERT INTO t200 VALUES (5, 5), (15, 15), (25, 25);
+ALTER TABLE t200 PARTITION BY RANGE( a ) (
+ PARTITION p0 VALUES LESS THAN (10),
+ PARTITION p1 VALUES LESS THAN (20),
+ PARTITION p2 VALUES LESS THAN (30)
+);
+CREATE TABLE t210(a INT, b INT) ENGINE ARIA TRANSACTIONAL = 1 PAGE_CHECKSUM = 1;
+--echo #TODO: echange partitions have not logged yet
+ALTER TABLE t200 EXCHANGE PARTITION p2 WITH TABLE t210;
+ALTER TABLE t200 DROP PARTITION p0;
+ALTER TABLE t200 ADD PARTITION (PARTITION p3 VALUES LESS THAN (40));
+ALTER TABLE t200
+ REORGANIZE PARTITION p3 INTO (
+ PARTITION n0 VALUES LESS THAN (35),
+ PARTITION n1 VALUES LESS THAN (45)
+);
+ALTER TABLE t200 PARTITION BY KEY(a) PARTITIONS 2;
+ALTER TABLE t200 PARTITION BY HASH(a) PARTITIONS 8;
+ALTER TABLE t200 COALESCE PARTITION 4;
+ALTER TABLE t200
+ PARTITION BY RANGE (b)
+ SUBPARTITION BY KEY (a)
+ SUBPARTITIONS 2 (
+ PARTITION p0 VALUES LESS THAN (10),
+ PARTITION p1 VALUES LESS THAN (20),
+ PARTITION p2 VALUES LESS THAN (30),
+ PARTITION p3 VALUES LESS THAN (MAXVALUE)
+ );
+ALTER TABLE t200 REMOVE PARTITIONING;
+DROP TABLE t200, t210;
+
+--echo # Test for the case when TDC contains TABLE_SHARE object for the
+--echo # certain table, but the table is not opened
+CREATE TABLE t220(a INT) ENGINE ARIA PARTITION BY HASH(a) PARTITIONS 2;
+--disable_result_log
+SELECT VERSION FROM INFORMATION_SCHEMA.tables WHERE
+ TABLE_SCHEMA = 'test' AND TABLE_NAME = 't220';
+--enable_result_log
+DROP TABLE t220;
+
+--source include/print_ddl_log.inc
+
+--echo #
+--echo # Cleanup
+--echo #
+disconnect con1;
diff --git a/mysql-test/suite/parts/t/backup_log_rocksdb.opt b/mysql-test/suite/parts/t/backup_log_rocksdb.opt
new file mode 100644
index 00000000000..df675545bf9
--- /dev/null
+++ b/mysql-test/suite/parts/t/backup_log_rocksdb.opt
@@ -0,0 +1 @@
+--plugin-load=$HA_ROCKSDB_SO
diff --git a/mysql-test/suite/parts/t/backup_log_rocksdb.test b/mysql-test/suite/parts/t/backup_log_rocksdb.test
new file mode 100644
index 00000000000..c260d26acc1
--- /dev/null
+++ b/mysql-test/suite/parts/t/backup_log_rocksdb.test
@@ -0,0 +1,24 @@
+--source include/have_partition.inc
+--source suite/mariabackup/include/have_rocksdb.inc
+--source include/not_embedded.inc
+
+#
+# Test that dynmaic loaded storage engines also works with partition and logging
+# This is will access code in dd_frm_type() that is not acccessed by other tests
+#
+
+connect (con1,localhost,root,,);
+BACKUP STAGE START;
+connection default;
+
+--echo # Test partition engine read from .frm
+CREATE TABLE t220 (a INT) ENGINE ROCKSDB PARTITION BY KEY(a) PARTITIONS 2;
+DROP TABLE t220;
+
+--source include/print_ddl_log.inc
+
+--echo #
+--echo # Cleanup
+--echo #
+
+disconnect con1;
diff --git a/sql/backup.cc b/sql/backup.cc
index e89f9a108a7..1b3007c5a00 100644
--- a/sql/backup.cc
+++ b/sql/backup.cc
@@ -34,6 +34,7 @@
#include "sql_insert.h" // kill_delayed_threads
#include "sql_handler.h" // mysql_ha_cleanup_no_free
#include <my_sys.h>
+#include <strfunc.h> // strconvert()
static const char *stage_names[]=
{"START", "FLUSH", "BLOCK_DDL", "BLOCK_COMMIT", "END", 0};
@@ -42,11 +43,15 @@ TYPELIB backup_stage_names=
{ array_elements(stage_names)-1, "", stage_names, 0 };
static MDL_ticket *backup_flush_ticket;
+static File volatile backup_log= -1;
+static int backup_log_error= 0;
static bool backup_start(THD *thd);
static bool backup_flush(THD *thd);
static bool backup_block_ddl(THD *thd);
static bool backup_block_commit(THD *thd);
+static bool start_ddl_logging();
+static void stop_ddl_logging();
/**
Run next stage of backup
@@ -55,6 +60,8 @@ static bool backup_block_commit(THD *thd);
void backup_init()
{
backup_flush_ticket= 0;
+ backup_log= -1;
+ backup_log_error= 0;
}
bool run_backup_stage(THD *thd, backup_stages stage)
@@ -152,7 +159,6 @@ static bool backup_start(THD *thd)
thd->current_backup_stage= BACKUP_FINISHED; // For next test
if (thd->has_read_only_protection())
DBUG_RETURN(1);
- thd->current_backup_stage= BACKUP_START;
if (thd->locked_tables_mode)
{
@@ -160,14 +166,31 @@ static bool backup_start(THD *thd)
DBUG_RETURN(1);
}
- MDL_REQUEST_INIT(&mdl_request, MDL_key::BACKUP, "", "", MDL_BACKUP_START,
+ /* this will be reset if this stage fails */
+ thd->current_backup_stage= BACKUP_START;
+
+ /*
+ Wait for old backup to finish and block ddl's so that we can start the
+ ddl logger
+ */
+ MDL_REQUEST_INIT(&mdl_request, MDL_key::BACKUP, "", "", MDL_BACKUP_BLOCK_DDL,
MDL_EXPLICIT);
if (thd->mdl_context.acquire_lock(&mdl_request,
thd->variables.lock_wait_timeout))
DBUG_RETURN(1);
+ if (start_ddl_logging())
+ {
+ thd->mdl_context.release_lock(mdl_request.ticket);
+ DBUG_RETURN(1);
+ }
+
+ DBUG_ASSERT(backup_flush_ticket == 0);
backup_flush_ticket= mdl_request.ticket;
+ /* Downgrade lock to only block other backups */
+ backup_flush_ticket->downgrade_lock(MDL_BACKUP_START);
+
ha_prepare_for_backup();
DBUG_RETURN(0);
}
@@ -216,7 +239,8 @@ static bool backup_flush(THD *thd)
- Kill all insert delay handlers, to ensure that all non transactional
tables are closed (can be improved in the future).
- - Close handlers as other threads may wait for these, which can cause deadlocks.
+ - Close handlers as other threads may wait for these, which can cause
+ deadlocks.
- Wait for all statements using write locked non-transactional tables to end.
@@ -271,9 +295,13 @@ static bool backup_block_ddl(THD *thd)
backup_flush_ticket->downgrade_lock(MDL_BACKUP_FLUSH);
DBUG_RETURN(1);
}
+
+ /* There can't be anything more that needs to be logged to ddl log */
+ stop_ddl_logging();
DBUG_RETURN(0);
}
+
/**
backup_block_commit()
@@ -303,6 +331,7 @@ static bool backup_block_commit(THD *thd)
DBUG_RETURN(0);
}
+
/**
backup_end()
@@ -316,9 +345,14 @@ bool backup_end(THD *thd)
if (thd->current_backup_stage != BACKUP_FINISHED)
{
+ DBUG_ASSERT(backup_flush_ticket);
+ MDL_ticket *old_ticket= backup_flush_ticket;
ha_end_backup();
+ // This is needed as we may call backup_end without backup_block_commit
+ stop_ddl_logging();
+ backup_flush_ticket= 0;
thd->current_backup_stage= BACKUP_FINISHED;
- thd->mdl_context.release_lock(backup_flush_ticket);
+ thd->mdl_context.release_lock(old_ticket);
}
DBUG_RETURN(0);
}
@@ -370,7 +404,7 @@ bool backup_reset_alter_copy_lock(THD *thd)
/*****************************************************************************
- Backup locks
+ Interfaces for BACKUP LOCK
These functions are used by maria_backup to ensure that there are no active
ddl's on the object the backup is going to copy
*****************************************************************************/
@@ -402,3 +436,135 @@ void backup_unlock(THD *thd)
thd->mdl_context.release_lock(thd->mdl_backup_lock);
thd->mdl_backup_lock= 0;
}
+
+
+/*****************************************************************************
+ Logging of ddl statements to backup log
+*****************************************************************************/
+
+static bool start_ddl_logging()
+{
+ char name[FN_REFLEN];
+ DBUG_ENTER("start_ddl_logging");
+
+ fn_format(name, "ddl", mysql_data_home, ".log", 0);
+
+ backup_log_error= 0;
+ backup_log= mysql_file_create(key_file_log_ddl, name, CREATE_MODE,
+ O_TRUNC | O_WRONLY | O_APPEND | O_NOFOLLOW,
+ MYF(MY_WME));
+ DBUG_RETURN(backup_log < 0);
+}
+
+static void stop_ddl_logging()
+{
+ mysql_mutex_lock(&LOCK_backup_log);
+ if (backup_log >= 0)
+ {
+ mysql_file_close(backup_log, MYF(MY_WME));
+ backup_log= -1;
+ }
+ backup_log_error= 0;
+ mysql_mutex_unlock(&LOCK_backup_log);
+}
+
+
+static inline char *add_str_to_buffer(char *ptr, const LEX_CSTRING *from)
+{
+ if (from->length) // If length == 0, str may be 0
+ memcpy(ptr, from->str, from->length);
+ ptr[from->length]= '\t';
+ return ptr+ from->length + 1;
+}
+
+static char *add_name_to_buffer(char *ptr, const LEX_CSTRING *from)
+{
+ LEX_CSTRING tmp;
+ char buff[NAME_LEN*4];
+ uint errors;
+
+ tmp.str= buff;
+ tmp.length= strconvert(system_charset_info, from->str, from->length,
+ &my_charset_filename, buff, sizeof(buff), &errors);
+ return add_str_to_buffer(ptr, &tmp);
+}
+
+
+static char *add_id_to_buffer(char *ptr, const LEX_CUSTRING *from)
+{
+ LEX_CSTRING tmp;
+ char buff[MY_UUID_STRING_LENGTH];
+
+ if (!from->length)
+ return add_str_to_buffer(ptr, (LEX_CSTRING*) from);
+
+ tmp.str= buff;
+ tmp.length= MY_UUID_STRING_LENGTH;
+ my_uuid2str(from->str, buff);
+ return add_str_to_buffer(ptr, &tmp);
+}
+
+
+static char *add_bool_to_buffer(char *ptr, bool value) {
+ *(ptr++) = value ? '1' : '0';
+ *(ptr++) = '\t';
+ return ptr;
+}
+
+/*
+ Write to backup log
+
+ Sets backup_log_error in case of error. The backup thread could check this
+ to ensure that all logging had succeded
+*/
+
+void backup_log_ddl(const backup_log_info *info)
+{
+ if (backup_log >= 0 && backup_log_error == 0)
+ {
+ mysql_mutex_lock(&LOCK_backup_log);
+ if (backup_log < 0)
+ {
+ mysql_mutex_unlock(&LOCK_backup_log);
+ return;
+ }
+ /* Enough place for db.table *2 + query + engine_name * 2 + tabs+ uuids */
+ char buff[NAME_CHAR_LEN*4+20+40*2+10+MY_UUID_STRING_LENGTH*2], *ptr= buff;
+ char timebuff[20];
+ struct tm current_time;
+ LEX_CSTRING tmp_lex;
+ time_t tmp_time= my_time(0);
+
+ localtime_r(&tmp_time, &current_time);
+ tmp_lex.str= timebuff;
+ tmp_lex.length= snprintf(timebuff, sizeof(timebuff),
+ "%4d-%02d-%02d %2d:%02d:%02d",
+ current_time.tm_year + 1900,
+ current_time.tm_mon+1,
+ current_time.tm_mday,
+ current_time.tm_hour,
+ current_time.tm_min,
+ current_time.tm_sec);
+ ptr= add_str_to_buffer(ptr, &tmp_lex);
+
+ ptr= add_str_to_buffer(ptr, &info->query);
+ ptr= add_str_to_buffer(ptr, &info->org_storage_engine_name);
+ ptr= add_bool_to_buffer(ptr, info->org_partitioned);
+ ptr= add_name_to_buffer(ptr, &info->org_database);
+ ptr= add_name_to_buffer(ptr, &info->org_table);
+ ptr= add_id_to_buffer(ptr, &info->org_table_id);
+
+ /* The following fields are only set in case of rename */
+ ptr= add_str_to_buffer(ptr, &info->new_storage_engine_name);
+ ptr= add_bool_to_buffer(ptr, info->new_partitioned);
+ ptr= add_name_to_buffer(ptr, &info->new_database);
+ ptr= add_name_to_buffer(ptr, &info->new_table);
+ ptr= add_id_to_buffer(ptr, &info->new_table_id);
+
+ ptr[-1]= '\n'; // Replace last tab with nl
+ if (mysql_file_write(backup_log, (uchar*) buff, (size_t) (ptr-buff),
+ MYF(MY_FNABP)))
+ backup_log_error= my_errno;
+ mysql_mutex_unlock(&LOCK_backup_log);
+ }
+}
diff --git a/sql/backup.h b/sql/backup.h
index 8d8a28b6082..2e5c3a58ba2 100644
--- a/sql/backup.h
+++ b/sql/backup.h
@@ -23,6 +23,18 @@ enum backup_stages
extern TYPELIB backup_stage_names;
+struct backup_log_info {
+ LEX_CSTRING query;
+ LEX_CUSTRING org_table_id; /* Unique id from frm */
+ LEX_CSTRING org_database, org_table;
+ LEX_CSTRING org_storage_engine_name;
+ LEX_CSTRING new_database, new_table;
+ LEX_CSTRING new_storage_engine_name;
+ LEX_CUSTRING new_table_id; /* Unique id from frm */
+ bool org_partitioned;
+ bool new_partitioned;
+};
+
void backup_init();
bool run_backup_stage(THD *thd, backup_stages stage);
bool backup_end(THD *thd);
@@ -31,4 +43,5 @@ bool backup_reset_alter_copy_lock(THD *thd);
bool backup_lock(THD *thd, TABLE_LIST *table);
void backup_unlock(THD *thd);
+void backup_log_ddl(const backup_log_info *info);
#endif /* BACKUP_INCLUDED */
diff --git a/sql/datadict.cc b/sql/datadict.cc
index 1321bf9a3a7..716b4dc3025 100644
--- a/sql/datadict.cc
+++ b/sql/datadict.cc
@@ -55,10 +55,12 @@ static int read_string(File file, uchar**to, size_t length)
@retval TABLE_TYPE_VIEW view
*/
-Table_type dd_frm_type(THD *thd, char *path, LEX_CSTRING *engine_name)
+Table_type dd_frm_type(THD *thd, char *path, LEX_CSTRING *engine_name,
+ LEX_CSTRING *partition_engine_name,
+ LEX_CUSTRING *table_version)
{
File file;
- uchar header[40]; //"TYPE=VIEW\n" it is 10 characters
+ uchar header[64+ MY_UUID_SIZE + 2]; // Header and uuid
size_t error;
Table_type type= TABLE_TYPE_UNKNOWN;
uchar dbt;
@@ -83,8 +85,18 @@ Table_type dd_frm_type(THD *thd, char *path, LEX_CSTRING *engine_name)
engine_name->length= 0;
((char*) (engine_name->str))[0]= 0;
}
-
- if (unlikely((error= mysql_file_read(file, (uchar*) header, sizeof(header), MYF(MY_NABP)))))
+ if (partition_engine_name)
+ {
+ partition_engine_name->length= 0;
+ partition_engine_name->str= 0;
+ }
+ if (table_version)
+ {
+ table_version->length= 0;
+ table_version->str= 0; // Allocated if needed
+ }
+ if (unlikely((error= mysql_file_read(file, (uchar*) header, sizeof(header),
+ MYF(MY_NABP)))))
goto err;
if (unlikely((!strncmp((char*) header, "TYPE=VIEW\n", 10))))
@@ -108,20 +120,41 @@ Table_type dd_frm_type(THD *thd, char *path, LEX_CSTRING *engine_name)
type= TABLE_TYPE_SEQUENCE;
}
+ if (table_version)
+ {
+ /* Read the table version (if it is a 'new' frm file) */
+ if (header[64] == EXTRA2_TABLEDEF_VERSION && header[65] == MY_UUID_SIZE)
+ if ((table_version->str= (uchar*) thd->memdup(header + 66, MY_UUID_SIZE)))
+ table_version->length= MY_UUID_SIZE;
+ }
+
/* cannot use ha_resolve_by_legacy_type without a THD */
if (thd && dbt < DB_TYPE_FIRST_DYNAMIC)
{
- handlerton *ht= ha_resolve_by_legacy_type(thd, (enum legacy_db_type)dbt);
+ handlerton *ht= ha_resolve_by_legacy_type(thd, (legacy_db_type) dbt);
if (ht)
{
*engine_name= hton2plugin[ht->slot]->name;
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ if (partition_engine_name && dbt == DB_TYPE_PARTITION_DB)
+ {
+ handlerton *p_ht;
+ legacy_db_type new_dbt= (legacy_db_type) header[61];
+ if (new_dbt >= DB_TYPE_FIRST_DYNAMIC)
+ goto cont;
+ if (!(p_ht= ha_resolve_by_legacy_type(thd, new_dbt)))
+ goto err;
+ *partition_engine_name= *hton_name(p_ht);
+ }
+#endif // WITH_PARTITION_STORAGE_ENGINE
goto err;
}
}
+cont:
/* read the true engine name */
{
- MY_STAT state;
+ MY_STAT state;
uchar *frm_image= 0;
uint n_length;
@@ -134,7 +167,8 @@ Table_type dd_frm_type(THD *thd, char *path, LEX_CSTRING *engine_name)
if (read_string(file, &frm_image, (size_t)state.st_size))
goto err;
- if ((n_length= uint4korr(frm_image+55)))
+ /* The test for !engine_name->length is only true for partition engine */
+ if (!engine_name->length && (n_length= uint4korr(frm_image+55)))
{
uint record_offset= uint2korr(frm_image+6)+
((uint2korr(frm_image+14) == 0xffff ?
@@ -160,6 +194,43 @@ Table_type dd_frm_type(THD *thd, char *path, LEX_CSTRING *engine_name)
}
}
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ if (partition_engine_name && dbt == DB_TYPE_PARTITION_DB)
+ {
+ uint len;
+ const uchar *extra2;
+ /* Length of the MariaDB extra2 segment in the form file. */
+ len = uint2korr(frm_image+4);
+ extra2= frm_image + 64;
+ if (*extra2 != '/') // old frm had '/' there
+ {
+ const uchar *e2end= extra2 + len;
+ while (extra2 + 3 <= e2end)
+ {
+ uchar type= *extra2++;
+ size_t length= *extra2++;
+ if (!length)
+ {
+ if (extra2 + 2 >= e2end)
+ break;
+ length= uint2korr(extra2);
+ extra2+= 2;
+ if (length < 256)
+ break;
+ }
+ if (extra2 + length > e2end)
+ break;
+ if (type == EXTRA2_DEFAULT_PART_ENGINE)
+ {
+ partition_engine_name->str= thd->strmake((char*)extra2, length);
+ partition_engine_name->length= length;
+ break;
+ }
+ extra2+= length;
+ }
+ }
+ }
+#endif // WITH_PARTITION_STORAGE_ENGINE
my_free(frm_image);
}
diff --git a/sql/datadict.h b/sql/datadict.h
index f4af592247a..bec093aa141 100644
--- a/sql/datadict.h
+++ b/sql/datadict.h
@@ -38,11 +38,13 @@ enum Table_type
To check whether it's an frm of a view, use dd_frm_is_view().
*/
-enum Table_type dd_frm_type(THD *thd, char *path, LEX_CSTRING *engine_name);
+enum Table_type dd_frm_type(THD *thd, char *path, LEX_CSTRING *engine_name,
+ LEX_CSTRING *partition_engine_name,
+ LEX_CUSTRING *table_version);
static inline bool dd_frm_is_view(THD *thd, char *path)
{
- return dd_frm_type(thd, path, NULL) == TABLE_TYPE_VIEW;
+ return dd_frm_type(thd, path, NULL, NULL, NULL) == TABLE_TYPE_VIEW;
}
bool dd_recreate_table(THD *thd, const char *db, const char *table_name);
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index f252c0c3137..dd9fea5937a 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -459,6 +459,11 @@ void ha_partition::init_handler_variables()
#endif
}
+const char *ha_partition::real_table_type() const
+{
+ // we can do this since we only support a single engine type
+ return m_file[0]->table_type();
+}
/*
Destructor method
@@ -3772,6 +3777,15 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
*/
clear_handler_file();
+ DBUG_ASSERT(part_share);
+ lock_shared_ha_data();
+ /* Protect against cloned file, for which we don't need engine name */
+ if (m_file[0])
+ part_share->partition_engine_name= real_table_type();
+ else
+ part_share->partition_engine_name= 0; // Checked in ha_table_exists()
+ unlock_shared_ha_data();
+
/*
Some handlers update statistics as part of the open call. This will in
some cases corrupt the statistics of the partition handler and thus
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index df204cd3d2d..15513b96b97 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -98,12 +98,14 @@ public:
*/
bool partition_name_hash_initialized;
HASH partition_name_hash;
+ const char *partition_engine_name;
/** Storage for each partitions Handler_share */
Parts_share_refs partitions_share_refs;
Partition_share()
: auto_inc_initialized(false),
next_auto_inc_val(0),
partition_name_hash_initialized(false),
+ partition_engine_name(NULL),
partition_names(NULL)
{
mysql_mutex_init(key_partition_auto_inc_mutex,
@@ -269,7 +271,7 @@ typedef struct st_partition_part_key_multi_range_hld
extern "C" int cmp_key_part_id(void *key_p, uchar *ref1, uchar *ref2);
extern "C" int cmp_key_rowid_part_id(void *ptr, uchar *ref1, uchar *ref2);
-class ha_partition :public handler
+class ha_partition final :public handler
{
private:
enum partition_index_scan_type
@@ -1071,6 +1073,8 @@ public:
*/
const char *index_type(uint inx) override;
+ /* The name of the table type that will be used for display purposes */
+ const char *real_table_type() const override;
/* The name of the row type used for the underlying tables. */
enum row_type get_row_type() const override;
@@ -1596,6 +1600,7 @@ public:
return h;
}
+ bool partition_engine() override { return 1;}
ha_rows part_records(partition_element *part_elem)
{
DBUG_ASSERT(m_part_info);
diff --git a/sql/handler.cc b/sql/handler.cc
index fa99c24771c..f6636c3b36f 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -997,6 +997,27 @@ void ha_end_backup()
PLUGIN_IS_DELETED|PLUGIN_IS_READY, 0);
}
+void handler::log_not_redoable_operation(const char *operation)
+{
+ DBUG_ENTER("log_not_redoable_operation");
+ if (table->s->tmp_table == NO_TMP_TABLE)
+ {
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ lex_string_set(&ddl_log.query, operation);
+ /*
+ We can't use partition_engine() here as this function is called
+ directly by the handler for the underlaying partition table
+ */
+ ddl_log.org_partitioned= table->s->partition_info_str != 0;
+ lex_string_set(&ddl_log.org_storage_engine_name, table_type());
+ ddl_log.org_database= table->s->db;
+ ddl_log.org_table= table->s->table_name;
+ ddl_log.org_table_id= table->s->tabledef_version;
+ backup_log_ddl(&ddl_log);
+ }
+ DBUG_VOID_RETURN;
+}
/*
Inform plugin of the server shutdown.
@@ -5856,7 +5877,8 @@ static my_bool discover_existence(THD *thd, plugin_ref plugin,
*/
bool ha_table_exists(THD *thd, const LEX_CSTRING *db,
- const LEX_CSTRING *table_name,
+ const LEX_CSTRING *table_name, LEX_CUSTRING *table_id,
+ LEX_CSTRING *partition_engine_name,
handlerton **hton, bool *is_sequence)
{
handlerton *dummy;
@@ -5870,17 +5892,42 @@ bool ha_table_exists(THD *thd, const LEX_CSTRING *db,
if (!is_sequence)
is_sequence= &dummy2;
*is_sequence= 0;
+ if (table_id)
+ {
+ table_id->str= 0;
+ table_id->length= 0;
+ }
TDC_element *element= tdc_lock_share(thd, db->str, table_name->str);
if (element && element != MY_ERRPTR)
{
- if (hton)
- *hton= element->share->db_type();
+ if (!hton)
+ hton= &dummy;
+ *hton= element->share->db_type();
+ if (partition_engine_name && element->share->db_type() == partition_hton)
+ {
+ if (!static_cast<Partition_share *>(element->share->ha_share)->
+ partition_engine_name)
+ {
+ /* Partition engine found, but table has never been opened */
+ tdc_unlock_share(element);
+ goto retry_from_frm;
+ }
+ lex_string_set(partition_engine_name,
+ static_cast<Partition_share *>(element->share->ha_share)->
+ partition_engine_name);
+ }
*is_sequence= element->share->table_type == TABLE_TYPE_SEQUENCE;
+ if (*hton != view_pseudo_hton && element->share->tabledef_version.length &&
+ table_id &&
+ (table_id->str= (uchar*)
+ thd->memdup(element->share->tabledef_version.str, MY_UUID_SIZE)))
+ table_id->length= MY_UUID_SIZE;
tdc_unlock_share(element);
DBUG_RETURN(TRUE);
}
+retry_from_frm:
char path[FN_REFLEN + 1];
size_t path_len = build_table_filename(path, sizeof(path) - 1,
db->str, table_name->str, "", 0);
@@ -5893,7 +5940,9 @@ bool ha_table_exists(THD *thd, const LEX_CSTRING *db,
{
char engine_buf[NAME_CHAR_LEN + 1];
LEX_CSTRING engine= { engine_buf, 0 };
- Table_type type= dd_frm_type(thd, path, &engine);
+ Table_type type= dd_frm_type(thd, path, &engine,
+ partition_engine_name,
+ table_id);
switch (type) {
case TABLE_TYPE_UNKNOWN:
@@ -5948,6 +5997,10 @@ bool ha_table_exists(THD *thd, const LEX_CSTRING *db,
if (hton && share)
{
*hton= share->db_type();
+ if (table_id && share->tabledef_version.length &&
+ (table_id->str=
+ (uchar*) thd->memdup(share->tabledef_version.str, MY_UUID_SIZE)))
+ table_id->length= MY_UUID_SIZE;
tdc_release_share(share);
}
diff --git a/sql/handler.h b/sql/handler.h
index 78ca0f92a38..18a1a4abf40 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1083,6 +1083,8 @@ typedef bool (stat_print_fn)(THD *thd, const char *type, size_t type_len,
enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX };
extern MYSQL_PLUGIN_IMPORT st_plugin_int *hton2plugin[MAX_HA];
+#define view_pseudo_hton ((handlerton *)1)
+
/* Transaction log maintains type definitions */
enum log_status
{
@@ -2227,9 +2229,11 @@ struct Table_scope_and_contents_source_pod_st // For trivial members
{
CHARSET_INFO *alter_table_convert_to_charset;
LEX_CUSTRING tabledef_version;
+ LEX_CUSTRING org_tabledef_version; /* version of dropped table */
LEX_CSTRING connect_string;
LEX_CSTRING comment;
LEX_CSTRING alias;
+ LEX_CSTRING org_storage_engine_name, new_storage_engine_name;
const char *password, *tablespace;
const char *data_file_name, *index_file_name;
ulonglong max_rows,min_rows;
@@ -4222,6 +4226,8 @@ public:
virtual void free_foreign_key_create_info(char* str) {}
/** The following can be called without an open handler */
virtual const char *table_type() const { return hton_name(ht)->str; }
+ /* The following is same as table_table(), except for partition engine */
+ virtual const char *real_table_type() const { return hton_name(ht)->str; }
const char **bas_ext() const { return ht->tablefile_extensions; }
virtual int get_default_no_partitions(HA_CREATE_INFO *create_info)
@@ -5099,6 +5105,7 @@ public:
/* XXX to be removed, see ha_partition::partition_ht() */
virtual handlerton *partition_ht() const
{ return ht; }
+ virtual bool partition_engine() { return 0;}
inline int ha_write_tmp_row(uchar *buf);
inline int ha_delete_tmp_row(uchar *buf);
inline int ha_update_tmp_row(const uchar * old_data, uchar * new_data);
@@ -5168,6 +5175,7 @@ public:
return (lower_case_table_names == 2 && !(ha_table_flags() & HA_FILE_BASED));
}
+ void log_not_redoable_operation(const char *operation);
protected:
Handler_share *get_ha_share_ptr();
void set_ha_share_ptr(Handler_share *arg_ha_share);
@@ -5210,7 +5218,8 @@ static inline enum legacy_db_type ha_legacy_type(const handlerton *db_type)
static inline const char *ha_resolve_storage_engine_name(const handlerton *db_type)
{
- return db_type == NULL ? "UNKNOWN" : hton_name(db_type)->str;
+ return (db_type == NULL ? "UNKNOWN" :
+ db_type == view_pseudo_hton ? "VIEW" : hton_name(db_type)->str);
}
static inline bool ha_check_storage_engine_flag(const handlerton *db_type, uint32 flag)
@@ -5223,8 +5232,6 @@ static inline bool ha_storage_engine_is_enabled(const handlerton *db_type)
return db_type && db_type->create;
}
-#define view_pseudo_hton ((handlerton *)1)
-
/* basic stuff */
int ha_init_errors(void);
int ha_init(void);
@@ -5292,6 +5299,8 @@ int ha_discover_table_names(THD *thd, LEX_CSTRING *db, MY_DIR *dirp,
Discovered_table_list *result, bool reusable);
bool ha_table_exists(THD *thd, const LEX_CSTRING *db,
const LEX_CSTRING *table_name,
+ LEX_CUSTRING *table_version= 0,
+ LEX_CSTRING *partition_engine_name= 0,
handlerton **hton= 0, bool *is_sequence= 0);
bool ha_check_if_updates_are_ignored(THD *thd, handlerton *hton,
const char *op);
diff --git a/sql/mdl.cc b/sql/mdl.cc
index e83ef151554..1bacdf8f67b 100644
--- a/sql/mdl.cc
+++ b/sql/mdl.cc
@@ -1584,7 +1584,7 @@ MDL_lock::MDL_object_lock::m_waiting_incompatible[MDL_TYPE_END]=
TD | + + + + + - - + + + + + + + |
SD | + + + + - - - + + + + + + + |
DDL | + + + - - - - + + + + - + + |
- BLOCK_DDL | + + + + + + + + + + - + + + |
+ BLOCK_DDL | - + + + + + + + + + - + + + |
ALTER_COP | + + + + + - - + + + + + + + |
COMMIT | + + + + - + - + + + + + + + |
@@ -1623,7 +1623,7 @@ const MDL_lock::bitmap_t
MDL_lock::MDL_backup_lock::m_granted_incompatible[MDL_BACKUP_END]=
{
/* MDL_BACKUP_START */
- MDL_BIT(MDL_BACKUP_START) | MDL_BIT(MDL_BACKUP_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT),
+ MDL_BIT(MDL_BACKUP_START) | MDL_BIT(MDL_BACKUP_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_BLOCK_DDL),
MDL_BIT(MDL_BACKUP_START),
MDL_BIT(MDL_BACKUP_START) | MDL_BIT(MDL_BACKUP_DML),
MDL_BIT(MDL_BACKUP_START) | MDL_BIT(MDL_BACKUP_DML) | MDL_BIT(MDL_BACKUP_DDL),
@@ -1639,7 +1639,7 @@ MDL_lock::MDL_backup_lock::m_granted_incompatible[MDL_BACKUP_END]=
/* MDL_BACKUP_DDL */
MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2) | MDL_BIT(MDL_BACKUP_BLOCK_DDL),
/* MDL_BACKUP_BLOCK_DDL */
- MDL_BIT(MDL_BACKUP_DDL),
+ MDL_BIT(MDL_BACKUP_START) | MDL_BIT(MDL_BACKUP_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_BLOCK_DDL) | MDL_BIT(MDL_BACKUP_DDL),
MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2),
/* MDL_BACKUP_COMMIT */
MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL2)
@@ -1650,7 +1650,7 @@ const MDL_lock::bitmap_t
MDL_lock::MDL_backup_lock::m_waiting_incompatible[MDL_BACKUP_END]=
{
/* MDL_BACKUP_START */
- MDL_BIT(MDL_BACKUP_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT),
+ MDL_BIT(MDL_BACKUP_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_BLOCK_DDL),
0,
0,
0,
@@ -1666,7 +1666,7 @@ MDL_lock::MDL_backup_lock::m_waiting_incompatible[MDL_BACKUP_END]=
/* MDL_BACKUP_DDL */
MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2) | MDL_BIT(MDL_BACKUP_BLOCK_DDL),
/* MDL_BACKUP_BLOCK_DDL */
- 0,
+ MDL_BIT(MDL_BACKUP_START),
MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2),
/* MDL_BACKUP_COMMIT */
MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL2)
@@ -2911,6 +2911,10 @@ void MDL_context::release_all_locks_for_name(MDL_ticket *name)
void MDL_ticket::downgrade_lock(enum_mdl_type type)
{
+ DBUG_ENTER("MDL_ticket::downgrade_lock");
+ DBUG_PRINT("enter",("old_type: %s new_type: %s",
+ get_type_name()->str,
+ get_type_name(type)->str));
/*
Do nothing if already downgraded. Used when we FLUSH TABLE under
LOCK TABLES and a table is listed twice in LOCK TABLES list.
@@ -2919,7 +2923,10 @@ void MDL_ticket::downgrade_lock(enum_mdl_type type)
here that target lock is weaker than existing lock.
*/
if (m_type == type || !has_stronger_or_equal_type(type))
- return;
+ {
+ DBUG_PRINT("info", ("Nothing to downgrade"));
+ DBUG_VOID_RETURN;
+ }
/* Only allow downgrade in some specific known cases */
DBUG_ASSERT((get_key()->mdl_namespace() != MDL_key::BACKUP &&
@@ -2927,6 +2934,7 @@ void MDL_ticket::downgrade_lock(enum_mdl_type type)
m_type == MDL_SHARED_NO_WRITE)) ||
(get_key()->mdl_namespace() == MDL_key::BACKUP &&
(m_type == MDL_BACKUP_DDL ||
+ m_type == MDL_BACKUP_BLOCK_DDL ||
m_type == MDL_BACKUP_WAIT_FLUSH)));
mysql_prlock_wrlock(&m_lock->m_rwlock);
@@ -2939,6 +2947,7 @@ void MDL_ticket::downgrade_lock(enum_mdl_type type)
m_lock->m_granted.add_ticket(this);
m_lock->reschedule_waiters();
mysql_prlock_unlock(&m_lock->m_rwlock);
+ DBUG_VOID_RETURN;
}
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index dff18b9585e..69ab896abf2 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -711,6 +711,7 @@ mysql_mutex_t LOCK_prepared_stmt_count;
#ifdef HAVE_OPENSSL
mysql_mutex_t LOCK_des_key_file;
#endif
+mysql_mutex_t LOCK_backup_log;
mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
mysql_rwlock_t LOCK_ssl_refresh;
mysql_rwlock_t LOCK_all_status_vars;
@@ -856,6 +857,7 @@ PSI_file_key key_file_binlog, key_file_binlog_cache, key_file_binlog_index,
key_file_dbopt, key_file_des_key_file, key_file_ERRMSG, key_select_to_file,
key_file_fileparser, key_file_frm, key_file_global_ddl_log, key_file_load,
key_file_loadfile, key_file_log_event_data, key_file_log_event_info,
+ key_file_log_ddl,
key_file_master_info, key_file_misc, key_file_partition_ddl_log,
key_file_pid, key_file_relay_log_info, key_file_send_file, key_file_tclog,
key_file_trg, key_file_trn, key_file_init;
@@ -881,7 +883,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
key_LOCK_crypt, key_LOCK_delayed_create,
key_LOCK_delayed_insert, key_LOCK_delayed_status, key_LOCK_error_log,
key_LOCK_gdl, key_LOCK_global_system_variables,
- key_LOCK_manager,
+ key_LOCK_manager, key_LOCK_backup_log,
key_LOCK_prepared_stmt_count,
key_LOCK_rpl_status, key_LOCK_server_started,
key_LOCK_status,
@@ -941,6 +943,7 @@ static PSI_mutex_info all_server_mutexes[]=
{ &key_delayed_insert_mutex, "Delayed_insert::mutex", 0},
{ &key_hash_filo_lock, "hash_filo::lock", 0},
{ &key_LOCK_active_mi, "LOCK_active_mi", PSI_FLAG_GLOBAL},
+ { &key_LOCK_backup_log, "LOCK_backup_log", PSI_FLAG_GLOBAL},
{ &key_LOCK_thread_id, "LOCK_thread_id", PSI_FLAG_GLOBAL},
{ &key_LOCK_crypt, "LOCK_crypt", PSI_FLAG_GLOBAL},
{ &key_LOCK_delayed_create, "LOCK_delayed_create", PSI_FLAG_GLOBAL},
@@ -2043,6 +2046,7 @@ static void clean_up_mutexes()
#endif /* HAVE_REPLICATION */
mysql_mutex_destroy(&LOCK_active_mi);
mysql_rwlock_destroy(&LOCK_ssl_refresh);
+ mysql_mutex_destroy(&LOCK_backup_log);
mysql_rwlock_destroy(&LOCK_sys_init_connect);
mysql_rwlock_destroy(&LOCK_sys_init_slave);
mysql_mutex_destroy(&LOCK_global_system_variables);
@@ -4340,6 +4344,7 @@ static int init_thread_environment()
MY_MUTEX_INIT_SLOW);
mysql_mutex_init(key_LOCK_commit_ordered, &LOCK_commit_ordered,
MY_MUTEX_INIT_SLOW);
+ mysql_mutex_init(key_LOCK_backup_log, &LOCK_backup_log, MY_MUTEX_INIT_FAST);
#ifdef HAVE_OPENSSL
mysql_mutex_init(key_LOCK_des_key_file,
@@ -8971,6 +8976,7 @@ static PSI_file_info all_server_files[]=
{ &key_file_global_ddl_log, "global_ddl_log", 0},
{ &key_file_load, "load", 0},
{ &key_file_loadfile, "LOAD_FILE", 0},
+ { &key_file_log_ddl, "log_ddl", 0},
{ &key_file_log_event_data, "log_event_data", 0},
{ &key_file_log_event_info, "log_event_info", 0},
{ &key_file_master_info, "master_info", 0},
diff --git a/sql/mysqld.h b/sql/mysqld.h
index b50b98e0dea..ddfec106b60 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -396,7 +396,7 @@ extern PSI_file_key key_file_binlog, key_file_binlog_cache,
key_file_loadfile, key_file_log_event_data, key_file_log_event_info,
key_file_master_info, key_file_misc, key_file_partition_ddl_log,
key_file_pid, key_file_relay_log_info, key_file_send_file, key_file_tclog,
- key_file_trg, key_file_trn, key_file_init;
+ key_file_trg, key_file_trn, key_file_init, key_file_log_ddl;
extern PSI_file_key key_file_query_log, key_file_slow_log;
extern PSI_file_key key_file_relaylog, key_file_relaylog_index,
key_file_relaylog_cache, key_file_relaylog_index_cache;
@@ -744,7 +744,7 @@ extern mysql_mutex_t
LOCK_error_log, LOCK_delayed_insert, LOCK_short_uuid_generator,
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
LOCK_active_mi, LOCK_manager, LOCK_user_conn,
- LOCK_prepared_stmt_count, LOCK_error_messages;
+ LOCK_prepared_stmt_count, LOCK_error_messages, LOCK_backup_log;
extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_global_system_variables;
extern mysql_rwlock_t LOCK_all_status_vars;
extern mysql_mutex_t LOCK_start_thread;
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index 3c2675d1d5d..c7d83676cc4 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -520,7 +520,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
bool need_repair_or_alter= 0;
wait_for_commit* suspended_wfc;
bool is_table_modified= false;
-
+ LEX_CUSTRING tabledef_version;
DBUG_ENTER("mysql_admin_table");
DBUG_PRINT("enter", ("extra_open_options: %u", extra_open_options));
@@ -574,12 +574,17 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
{
char table_name_buff[SAFE_NAME_LEN*2+2];
LEX_CSTRING table_name= { table_name_buff, 0};
+ char storage_engine_name[NAME_LEN];
+ bool storage_engine_partitioned= 0;
+ uchar tabledef_version_buff[MY_UUID_SIZE];
const char *db= table->db.str;
bool fatal_error=0;
bool open_error;
bool collect_eis= FALSE;
bool open_for_modify= org_open_for_modify;
+ storage_engine_name[0]= 0; // Marker that's not used
+
DBUG_PRINT("admin", ("table: '%s'.'%s'", db, table->table_name.str));
DEBUG_SYNC(thd, "admin_command_kill_before_modify");
@@ -795,6 +800,16 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
thd->close_unused_temporary_table_instances(tables);
else
{
+ /* Store information about table for ddl log */
+ storage_engine_partitioned= table->table->file->partition_engine();
+ strmake(storage_engine_name, table->table->file->real_table_type(),
+ sizeof(storage_engine_name)-1);
+ tabledef_version.str= tabledef_version_buff;
+ if ((tabledef_version.length= table->table->s->tabledef_version.length))
+ memcpy((char*) tabledef_version.str,
+ table->table->s->tabledef_version.str,
+ MY_UUID_SIZE);
+
if (wait_while_table_is_used(thd, table->table, HA_EXTRA_NOT_USED))
goto err;
DEBUG_SYNC(thd, "after_admin_flush");
@@ -1246,6 +1261,7 @@ send_result_message:
with conflicting DMLs resulting in deadlock.
*/
thd->transaction->stmt.mark_executed_table_admin_cmd();
+
if (table->table && !table->view)
{
/*
@@ -1292,6 +1308,22 @@ send_result_message:
is_table_modified= true;
}
close_thread_tables(thd);
+
+ if (storage_engine_name[0])
+ {
+ /* Table was changed (repair, optimize or something similar) */
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ lex_string_set(&ddl_log.org_storage_engine_name,
+ storage_engine_name);
+ ddl_log.query= *operator_name;
+ ddl_log.org_partitioned= storage_engine_partitioned;
+ ddl_log.org_database= table->db;
+ ddl_log.org_table= table->table_name;
+ ddl_log.org_table_id= tabledef_version;
+ backup_log_ddl(&ddl_log);
+ }
+
thd->release_transactional_locks();
/*
diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc
index 9af4dfde77d..5827b7b104b 100644
--- a/sql/sql_alter.cc
+++ b/sql/sql_alter.cc
@@ -280,10 +280,8 @@ Alter_table_ctx::Alter_table_ctx(THD *thd, TABLE_LIST *table_list,
tables_opened(tables_opened_arg),
new_db(*new_db_arg), new_name(*new_name_arg),
fk_error_if_delete_row(false), fk_error_id(NULL),
- fk_error_table(NULL)
-#ifdef DBUG_ASSERT_EXISTS
- , tmp_table(false)
-#endif
+ fk_error_table(NULL),
+ tmp_table(false)
{
/*
Assign members db, table_name, new_db and new_name
@@ -362,10 +360,22 @@ Alter_table_ctx::Alter_table_ctx(THD *thd, TABLE_LIST *table_list,
this case. This fact is enforced with assert.
*/
build_tmptable_filename(thd, tmp_path, sizeof(tmp_path));
-#ifdef DBUG_ASSERT_EXISTS
tmp_table= true;
-#endif
}
+ if ((id.length= table_list->table->s->tabledef_version.length))
+ memcpy(id_buff, table_list->table->s->tabledef_version.str, MY_UUID_SIZE);
+ id.str= id_buff;
+ storage_engine_partitioned= table_list->table->file->partition_engine();
+ storage_engine_name.str= storage_engine_buff;
+ storage_engine_name.length= ((strmake(storage_engine_buff,
+ table_list->table->file->
+ real_table_type(),
+ sizeof(storage_engine_buff)-1)) -
+ storage_engine_buff);
+ tmp_storage_engine_name.str= tmp_storage_engine_buff;
+ tmp_storage_engine_name.length= 0;
+ tmp_id.str= 0;
+ tmp_id.length= 0;
}
diff --git a/sql/sql_alter.h b/sql/sql_alter.h
index b8aa2595a58..a0f89c28d2a 100644
--- a/sql/sql_alter.h
+++ b/sql/sql_alter.h
@@ -318,12 +318,19 @@ public:
uint tables_opened;
LEX_CSTRING db;
LEX_CSTRING table_name;
+ LEX_CSTRING storage_engine_name;
LEX_CSTRING alias;
LEX_CSTRING new_db;
LEX_CSTRING new_name;
LEX_CSTRING new_alias;
LEX_CSTRING tmp_name;
+ LEX_CSTRING tmp_storage_engine_name;
+ LEX_CUSTRING tmp_id, id;
char tmp_buff[80];
+ uchar id_buff[MY_UUID_SIZE];
+ char storage_engine_buff[NAME_LEN], tmp_storage_engine_buff[NAME_LEN];
+ bool storage_engine_partitioned;
+ bool tmp_storage_engine_name_partitioned;
/**
Indicates that if a row is deleted during copying of data from old version
@@ -335,6 +342,8 @@ public:
const char *fk_error_id;
/** Name of table for the above error. */
const char *fk_error_table;
+ /** Indicates that we are altering temporary table */
+ bool tmp_table;
private:
char new_filename[FN_REFLEN + 1];
@@ -344,11 +353,6 @@ private:
char new_path[FN_REFLEN + 1];
char tmp_path[FN_REFLEN + 1];
-#ifdef DBUG_ASSERT_EXISTS
- /** Indicates that we are altering temporary table. Used only in asserts. */
- bool tmp_table;
-#endif
-
Alter_table_ctx &operator=(const Alter_table_ctx &rhs); // not implemented
Alter_table_ctx(const Alter_table_ctx &rhs); // not implemented
};
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 71af78d135d..4a01ecd97da 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -3926,7 +3926,7 @@ static bool upgrade_lock_if_not_exists(THD *thd,
DEBUG_SYNC(thd,"create_table_before_check_if_exists");
if (!create_info.or_replace() &&
ha_table_exists(thd, &create_table->db, &create_table->table_name,
- &create_table->db_type))
+ NULL, NULL, &create_table->db_type))
{
if (create_info.if_not_exists())
{
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 92d9e90adc1..7d4467c78ca 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -637,6 +637,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
thread_dbug_id(id),
os_thread_id(0),
global_disable_checkpoint(0),
+ current_backup_stage(BACKUP_FINISHED),
failed_com_change_user(0),
is_fatal_error(0),
transaction_rollback_request(0),
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 4fd90a0e0b1..090b87af4ff 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -789,7 +789,6 @@ mysql_create_db_internal(THD *thd, const LEX_CSTRING *db,
DBUG_RETURN(-1);
}
-
if (my_mkdir(path, 0777, MYF(0)) < 0)
{
my_error(ER_CANT_CREATE_DB, MYF(0), db->str, my_errno);
@@ -815,6 +814,14 @@ mysql_create_db_internal(THD *thd, const LEX_CSTRING *db,
thd->clear_error();
}
+ /* Log command to ddl log */
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ ddl_log.query= { C_STRING_WITH_LEN("CREATE") };
+ ddl_log.org_storage_engine_name= { C_STRING_WITH_LEN("DATABASE") };
+ ddl_log.org_database= *db;
+ backup_log_ddl(&ddl_log);
+
not_silent:
if (!silent)
{
@@ -898,6 +905,14 @@ mysql_alter_db_internal(THD *thd, const LEX_CSTRING *db,
thd->variables.collation_database= thd->db_charset;
}
+ /* Log command to ddl log */
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ ddl_log.query= { C_STRING_WITH_LEN("ALTER") };
+ ddl_log.org_storage_engine_name= { C_STRING_WITH_LEN("DATABASE") };
+ ddl_log.org_database= *db;
+ backup_log_ddl(&ddl_log);
+
if (mysql_bin_log.is_open())
{
int errcode= query_error_code(thd, TRUE);
@@ -1148,6 +1163,17 @@ mysql_rm_db_internal(THD *thd, const LEX_CSTRING *db, bool if_exists,
thd->pop_internal_handler();
update_binlog:
+ if (likely(!error))
+ {
+ /* Log command to ddl log */
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ ddl_log.query= { C_STRING_WITH_LEN("DROP") };
+ ddl_log.org_storage_engine_name= { C_STRING_WITH_LEN("DATABASE") };
+ ddl_log.org_database= *db;
+ backup_log_ddl(&ddl_log);
+ }
+
if (!silent && likely(!error))
{
const char *query;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 54fb94e8e4f..9bdd40010df 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -5034,6 +5034,20 @@ bool select_create::send_eof()
mysql_mutex_unlock(&thd->LOCK_thd_data);
}
#endif /* WITH_WSREP */
+
+ /* Log query to ddl log */
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ ddl_log.query= { C_STRING_WITH_LEN("CREATE") };
+ if ((ddl_log.org_partitioned= (create_info->db_type == partition_hton)))
+ ddl_log.org_storage_engine_name= create_info->new_storage_engine_name;
+ else
+ lex_string_set(&ddl_log.org_storage_engine_name,
+ ha_resolve_storage_engine_name(create_info->db_type));
+ ddl_log.org_database= create_table->db;
+ ddl_log.org_table= create_table->table_name;
+ ddl_log.org_table_id= create_info->tabledef_version;
+ backup_log_ddl(&ddl_log);
}
/*
If are using statement based replication the table will be deleted here
@@ -5154,21 +5168,39 @@ void select_create::abort_result_set()
drop_open_table(thd, table, &create_table->db, &create_table->table_name);
table=0; // Safety
- if (thd->log_current_statement && mysql_bin_log.is_open())
+ if (thd->log_current_statement)
{
- /* Remove logging of drop, create + insert rows */
- binlog_reset_cache(thd);
- /* Original table was deleted. We have to log it */
- if (table_creation_was_logged)
+ if (mysql_bin_log.is_open())
+ {
+ /* Remove logging of drop, create + insert rows */
+ binlog_reset_cache(thd);
+ /* Original table was deleted. We have to log it */
+ if (table_creation_was_logged)
+ {
+ thd->binlog_xid= thd->query_id;
+ ddl_log_update_xid(&ddl_log_state_create, thd->binlog_xid);
+ ddl_log_update_xid(&ddl_log_state_rm, thd->binlog_xid);
+ debug_crash_here("ddl_log_create_before_binlog");
+ log_drop_table(thd, &create_table->db, &create_table->table_name,
+ &create_info->org_storage_engine_name,
+ create_info->db_type == partition_hton,
+ &create_info->tabledef_version,
+ tmp_table);
+ debug_crash_here("ddl_log_create_after_binlog");
+ thd->binlog_xid= 0;
+ }
+ }
+ else if (!tmp_table)
{
- thd->binlog_xid= thd->query_id;
- ddl_log_update_xid(&ddl_log_state_create, thd->binlog_xid);
- ddl_log_update_xid(&ddl_log_state_rm, thd->binlog_xid);
- debug_crash_here("ddl_log_create_before_binlog");
- log_drop_table(thd, &create_table->db, &create_table->table_name,
- tmp_table);
- debug_crash_here("ddl_log_create_after_binlog");
- thd->binlog_xid= 0;
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ ddl_log.query= { C_STRING_WITH_LEN("DROP_AFTER_CREATE") };
+ ddl_log.org_partitioned= (create_info->db_type == partition_hton);
+ ddl_log.org_storage_engine_name= create_info->org_storage_engine_name;
+ ddl_log.org_database= create_table->db;
+ ddl_log.org_table= create_table->table_name;
+ ddl_log.org_table_id= create_info->tabledef_version;
+ backup_log_ddl(&ddl_log);
}
}
}
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 07926712583..397b8a8a350 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -7035,6 +7035,30 @@ static void downgrade_mdl_if_lock_tables_mode(THD *thd, MDL_ticket *ticket,
}
+bool log_partition_alter_to_ddl_log(ALTER_PARTITION_PARAM_TYPE *lpt)
+{
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ LEX_CSTRING old_engine_lex;
+ lex_string_set(&old_engine_lex, lpt->table->file->real_table_type());
+
+ ddl_log.query= { C_STRING_WITH_LEN("ALTER") };
+ ddl_log.org_storage_engine_name= old_engine_lex;
+ ddl_log.org_partitioned= true;
+ ddl_log.org_database= lpt->db;
+ ddl_log.org_table= lpt->table_name;
+ ddl_log.org_table_id= lpt->org_tabledef_version;
+ ddl_log.new_storage_engine_name= old_engine_lex;
+ ddl_log.new_partitioned= true;
+ ddl_log.new_database= lpt->db;
+ ddl_log.new_table= lpt->table_name;
+ ddl_log.new_table_id= lpt->create_info->tabledef_version;
+ backup_log_ddl(&ddl_log); // This sets backup_log_error on failure
+ return 0;
+}
+
+
+
/**
Actually perform the change requested by ALTER TABLE of partitions
previously prepared.
@@ -7087,6 +7111,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
lpt->key_count= 0;
lpt->db= *db;
lpt->table_name= *table_name;
+ lpt->org_tabledef_version= table->s->tabledef_version;
lpt->copied= 0;
lpt->deleted= 0;
lpt->pack_frm_data= NULL;
@@ -7224,6 +7249,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
ERROR_INJECT_ERROR("fail_drop_partition_6") ||
(frm_install= TRUE, FALSE) ||
mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
+ log_partition_alter_to_ddl_log(lpt) ||
(frm_install= FALSE, FALSE) ||
ERROR_INJECT_CRASH("crash_drop_partition_7") ||
ERROR_INJECT_ERROR("fail_drop_partition_7") ||
@@ -7303,6 +7329,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
ERROR_INJECT_ERROR("fail_add_partition_8") ||
(frm_install= TRUE, FALSE) ||
mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
+ log_partition_alter_to_ddl_log(lpt) ||
(frm_install= FALSE, FALSE) ||
ERROR_INJECT_CRASH("crash_add_partition_9") ||
ERROR_INJECT_ERROR("fail_add_partition_9") ||
@@ -7401,6 +7428,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
ERROR_INJECT_ERROR("fail_change_partition_8") ||
((frm_install= TRUE), FALSE) ||
mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
+ log_partition_alter_to_ddl_log(lpt) ||
(frm_install= FALSE, FALSE) ||
ERROR_INJECT_CRASH("crash_change_partition_9") ||
ERROR_INJECT_ERROR("fail_change_partition_9") ||
diff --git a/sql/sql_partition.h b/sql/sql_partition.h
index 58ba82dcd9f..57e6d0600ed 100644
--- a/sql/sql_partition.h
+++ b/sql/sql_partition.h
@@ -59,6 +59,7 @@ typedef struct st_lock_param_type
KEY *key_info_buffer;
LEX_CSTRING db;
LEX_CSTRING table_name;
+ LEX_CUSTRING org_tabledef_version;
uchar *pack_frm_data;
uint key_count;
uint db_options;
diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc
index ca564af1bf6..1056998ef08 100644
--- a/sql/sql_partition_admin.cc
+++ b/sql/sql_partition_admin.cc
@@ -507,6 +507,16 @@ bool Sql_cmd_alter_table_exchange_partition::
char part_file_name[2*FN_REFLEN+1];
char swap_file_name[FN_REFLEN+1];
char temp_file_name[FN_REFLEN+1];
+ char part_table_name[NAME_LEN + 1];
+ char part_db[NAME_LEN + 1];
+ char swap_table_name[NAME_LEN + 1];
+ char swap_db[NAME_LEN + 1];
+ uchar part_tabledef_version[MY_UUID_SIZE];
+ uchar swap_tabledef_version[MY_UUID_SIZE];
+
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+
uint swap_part_id;
uint part_file_name_len;
Alter_table_prelocking_strategy alter_prelocking_strategy;
@@ -576,6 +586,35 @@ bool Sql_cmd_alter_table_exchange_partition::
HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE)
force_if_exists= 1;
+ ddl_log.org_table.str= part_table_name;
+ DBUG_ASSERT(part_table->s->table_name.length <= NAME_LEN);
+ ddl_log.org_table.length= part_table->s->table_name.length;
+ strmake(part_table_name, part_table->s->table_name.str, NAME_LEN);
+
+ ddl_log.org_database.str= part_db;
+ DBUG_ASSERT(part_table->s->db.length <= NAME_LEN);
+ ddl_log.org_database.length= part_table->s->db.length;
+ strmake(part_db, part_table->s->db.str, NAME_LEN);
+
+ ddl_log.new_table.str= swap_table_name;
+ DBUG_ASSERT(swap_table->s->table_name.length <= NAME_LEN);
+ ddl_log.new_table.length= swap_table->s->table_name.length;
+ strmake(swap_table_name, swap_table->s->table_name.str, NAME_LEN);
+
+ ddl_log.new_database.str= swap_db;
+ DBUG_ASSERT(swap_table->s->db.length <= NAME_LEN);
+ ddl_log.new_database.length= swap_table->s->db.length;
+ strmake(swap_db, swap_table->s->db.str, NAME_LEN);
+
+ memcpy(part_tabledef_version, part_table->s->tabledef_version.str,
+ MY_UUID_SIZE);
+ ddl_log.org_table_id.str= part_tabledef_version;
+ ddl_log.org_table_id.length= MY_UUID_SIZE;
+ memcpy(swap_tabledef_version, swap_table->s->tabledef_version.str,
+ MY_UUID_SIZE);
+ ddl_log.new_table_id.str= swap_tabledef_version;
+ ddl_log.new_table_id.length= MY_UUID_SIZE;
+
/* set lock pruning on first table */
partition_name= alter_info->partition_names.head();
if (unlikely(table_list->table->part_info->
@@ -586,7 +625,6 @@ bool Sql_cmd_alter_table_exchange_partition::
if (unlikely(lock_tables(thd, table_list, table_counter, 0)))
DBUG_RETURN(true);
-
table_hton= swap_table->file->ht;
THD_STAGE_INFO(thd, stage_verifying_table);
@@ -690,6 +728,15 @@ bool Sql_cmd_alter_table_exchange_partition::
(void) exchange_name_with_ddl_log(thd, part_file_name, swap_file_name,
temp_file_name, table_hton);
}
+ else
+ {
+ ddl_log.query= { C_STRING_WITH_LEN("EXCHANGE_PARTITION") };
+ ddl_log.org_partitioned= true;
+ ddl_log.new_partitioned= false;
+ ddl_log.org_storage_engine_name= *hton_name(table_hton);
+ ddl_log.new_storage_engine_name= *hton_name(table_hton);
+ backup_log_ddl(&ddl_log);
+ }
thd->variables.option_bits= save_option_bits;
err:
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 195267b9abc..61cf204d721 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -1724,7 +1724,8 @@ int plugin_init(int *argc, char **argv, int flags)
{
char path[FN_REFLEN + 1];
build_table_filename(path, sizeof(path) - 1, "mysql", "plugin", reg_ext, 0);
- Table_type ttype= dd_frm_type(0, path, &plugin_table_engine_name);
+ Table_type ttype= dd_frm_type(0, path, &plugin_table_engine_name,
+ NULL, NULL);
if (ttype != TABLE_TYPE_NORMAL)
plugin_table_engine_name=empty_clex_str;
}
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 205c3ce91b7..094578874a8 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -234,6 +234,7 @@ do_rename_temporary(THD *thd, TABLE_LIST *ren_table, TABLE_LIST *new_table)
struct rename_param
{
LEX_CSTRING old_alias, new_alias;
+ LEX_CUSTRING old_version;
handlerton *from_table_hton;
};
@@ -281,6 +282,7 @@ check_rename(THD *thd, rename_param *param,
DBUG_ASSERT(param->new_alias.str);
if (!ha_table_exists(thd, &ren_table->db, &param->old_alias,
+ &param->old_version, NULL,
&param->from_table_hton) ||
!param->from_table_hton)
{
@@ -301,7 +303,7 @@ check_rename(THD *thd, rename_param *param,
DBUG_RETURN(-1);
}
- if (ha_table_exists(thd, new_db, &param->new_alias, 0))
+ if (ha_table_exists(thd, new_db, &param->new_alias, NULL, NULL, 0))
{
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), param->new_alias.str);
DBUG_RETURN(1); // This can't be skipped
@@ -379,7 +381,7 @@ do_rename(THD *thd, rename_param *param, DDL_LOG_STATE *ddl_log_state,
debug_crash_here("ddl_log_rename_before_rename_table");
if (!(rc= mysql_rename_table(hton, &ren_table->db, old_alias,
- new_db, new_alias, 0)))
+ new_db, new_alias, &param->old_version, 0)))
{
/* Table rename succeded.
It's safe to start recovery at rename trigger phase
@@ -413,7 +415,8 @@ do_rename(THD *thd, rename_param *param, DDL_LOG_STATE *ddl_log_state,
*/
debug_crash_here("ddl_log_rename_after_failed_rename_trigger");
(void) mysql_rename_table(hton, new_db, new_alias,
- &ren_table->db, old_alias, NO_FK_CHECKS);
+ &ren_table->db, old_alias, &param->old_version,
+ NO_FK_CHECKS);
debug_crash_here("ddl_log_rename_after_revert_rename_table");
ddl_log_disable_entry(ddl_log_state);
debug_crash_here("ddl_log_rename_after_disable_entry");
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 8e7e042264b..a2cd4e232f5 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -4515,7 +4515,7 @@ static void get_table_engine_for_i_s(THD *thd, char *buf, TABLE_LIST *tl,
char path[FN_REFLEN];
build_table_filename(path, sizeof(path) - 1,
db->str, table->str, reg_ext, 0);
- if (dd_frm_type(thd, path, &engine_name) == TABLE_TYPE_NORMAL)
+ if (dd_frm_type(thd, path, &engine_name, NULL, NULL) == TABLE_TYPE_NORMAL)
tl->option= engine_name.str;
}
}
@@ -4735,7 +4735,9 @@ static int fill_schema_table_names(THD *thd, TABLE_LIST *tables,
CHARSET_INFO *cs= system_charset_info;
handlerton *hton;
bool is_sequence;
- if (ha_table_exists(thd, db_name, table_name, &hton, &is_sequence))
+
+ if (ha_table_exists(thd, db_name, table_name, NULL, NULL,
+ &hton, &is_sequence))
{
if (hton == view_pseudo_hton)
table->field[3]->store(STRING_WITH_LEN("VIEW"), cs);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index f1390f232f1..ef92068c0d2 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1150,6 +1150,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
TABLE_LIST *table;
char path[FN_REFLEN + 1];
LEX_CSTRING alias= null_clex_str;
+ LEX_CUSTRING version;
+ LEX_CSTRING partition_engine_name= {NULL, 0};
StringBuffer<160> unknown_tables(system_charset_info);
DDL_LOG_STATE local_ddl_log_state;
const char *comment_start;
@@ -1157,9 +1159,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
int error= 0;
uint32 comment_len;
bool trans_tmp_table_deleted= 0, non_trans_tmp_table_deleted= 0;
- bool non_tmp_table_deleted= 0;
- bool is_drop_tmp_if_exists_added= 0;
- bool was_view= 0, was_table= 0, log_if_exists= if_exists;
+ bool is_drop_tmp_if_exists_added= 0, non_tmp_table_deleted= 0;
+ bool log_if_exists= if_exists;
const LEX_CSTRING *object_to_drop= ((drop_sequence) ?
&SEQUENCE_clex_str :
&TABLE_clex_str);
@@ -1233,6 +1234,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
bool table_creation_was_logged= 0;
bool wrong_drop_sequence= 0;
bool table_dropped= 0, res;
+ bool is_temporary= 0;
+ bool was_view= 0, was_table= 0;
const LEX_CSTRING db= table->db;
const LEX_CSTRING table_name= table->table_name;
LEX_CSTRING cpath= {0,0};
@@ -1299,6 +1302,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
table->table= 0;
temporary_table_was_dropped= 1;
}
+ is_temporary= 1;
}
if ((drop_temporary && if_exists) || temporary_table_was_dropped)
@@ -1376,7 +1380,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
char engine_buf[NAME_CHAR_LEN + 1];
LEX_CSTRING engine= { engine_buf, 0 };
- table_type= dd_frm_type(thd, path, &engine);
+ table_type= dd_frm_type(thd, path, &engine, &partition_engine_name,
+ &version);
if (table_type == TABLE_TYPE_NORMAL || table_type == TABLE_TYPE_SEQUENCE)
{
plugin_ref p= plugin_lock_by_name(thd, &engine,
@@ -1458,8 +1463,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
&table_name);
if (res)
{
- error= -1;
- goto err;
+ error= -1;
+ goto err;
}
debug_crash_here("ddl_log_drop_before_delete_table");
@@ -1634,6 +1639,21 @@ report_error:
db.str, (uint)db.length,
table_name.str, (uint)table_name.length);
mysql_audit_drop_table(thd, table);
+ if (!is_temporary)
+ {
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ ddl_log.query= { C_STRING_WITH_LEN("DROP") };
+ if ((ddl_log.org_partitioned= (partition_engine_name.str != 0)))
+ ddl_log.org_storage_engine_name= partition_engine_name;
+ else
+ lex_string_set(&ddl_log.org_storage_engine_name,
+ ha_resolve_storage_engine_name(hton));
+ ddl_log.org_database= table->db;
+ ddl_log.org_table= table->table_name;
+ ddl_log.org_table_id= version;
+ backup_log_ddl(&ddl_log);
+ }
}
if (!was_view)
ddl_log_update_phase(ddl_log_state, DDL_DROP_PHASE_BINLOG);
@@ -1696,27 +1716,27 @@ err:
debug_crash_here("ddl_log_drop_before_binlog");
if (non_trans_tmp_table_deleted)
{
- /* Chop of the last comma */
- built_non_trans_tmp_query.chop();
- built_non_trans_tmp_query.append(generated_by_server);
- error |= (thd->binlog_query(THD::STMT_QUERY_TYPE,
- built_non_trans_tmp_query.ptr(),
- built_non_trans_tmp_query.length(),
- FALSE, FALSE,
- is_drop_tmp_if_exists_added,
- 0) > 0);
+ /* Chop of the last comma */
+ built_non_trans_tmp_query.chop();
+ built_non_trans_tmp_query.append(generated_by_server);
+ error |= (thd->binlog_query(THD::STMT_QUERY_TYPE,
+ built_non_trans_tmp_query.ptr(),
+ built_non_trans_tmp_query.length(),
+ FALSE, FALSE,
+ is_drop_tmp_if_exists_added,
+ 0) > 0);
}
if (trans_tmp_table_deleted)
{
- /* Chop of the last comma */
- built_trans_tmp_query.chop();
- built_trans_tmp_query.append(generated_by_server);
- error |= (thd->binlog_query(THD::STMT_QUERY_TYPE,
- built_trans_tmp_query.ptr(),
- built_trans_tmp_query.length(),
- TRUE, FALSE,
- is_drop_tmp_if_exists_added,
- 0) > 0);
+ /* Chop of the last comma */
+ built_trans_tmp_query.chop();
+ built_trans_tmp_query.append(generated_by_server);
+ error |= (thd->binlog_query(THD::STMT_QUERY_TYPE,
+ built_trans_tmp_query.ptr(),
+ built_trans_tmp_query.length(),
+ TRUE, FALSE,
+ is_drop_tmp_if_exists_added,
+ 0) > 0);
}
if (non_tmp_table_deleted)
{
@@ -1812,41 +1832,56 @@ end:
bool log_drop_table(THD *thd, const LEX_CSTRING *db_name,
const LEX_CSTRING *table_name,
+ const LEX_CSTRING *handler_name,
+ bool partitioned,
+ const LEX_CUSTRING *id,
bool temporary_table)
{
char buff[NAME_LEN*2 + 80];
String query(buff, sizeof(buff), system_charset_info);
- bool error;
+ bool error= 0;
DBUG_ENTER("log_drop_table");
- if (!mysql_bin_log.is_open())
- DBUG_RETURN(0);
-
- query.length(0);
- query.append(STRING_WITH_LEN("DROP "));
- if (temporary_table)
- query.append(STRING_WITH_LEN("TEMPORARY "));
- query.append(STRING_WITH_LEN("TABLE IF EXISTS "));
- append_identifier(thd, &query, db_name);
- query.append('.');
- append_identifier(thd, &query, table_name);
- query.append(STRING_WITH_LEN("/* Generated to handle "
- "failed CREATE OR REPLACE */"));
+ if (mysql_bin_log.is_open())
+ {
+ query.length(0);
+ query.append(STRING_WITH_LEN("DROP "));
+ if (temporary_table)
+ query.append(STRING_WITH_LEN("TEMPORARY "));
+ query.append(STRING_WITH_LEN("TABLE IF EXISTS "));
+ append_identifier(thd, &query, db_name);
+ query.append('.');
+ append_identifier(thd, &query, table_name);
+ query.append(STRING_WITH_LEN("/* Generated to handle "
+ "failed CREATE OR REPLACE */"));
- /*
- In case of temporary tables we don't have to log the database name
- in the binary log. We log this for non temporary tables, as the slave
- may use a filter to ignore queries for a specific database.
- */
- error= thd->binlog_query(THD::STMT_QUERY_TYPE,
- query.ptr(), query.length(),
- FALSE, FALSE, temporary_table, 0) > 0;
+ /*
+ In case of temporary tables we don't have to log the database name
+ in the binary log. We log this for non temporary tables, as the slave
+ may use a filter to ignore queries for a specific database.
+ */
+ error= thd->binlog_query(THD::STMT_QUERY_TYPE,
+ query.ptr(), query.length(),
+ FALSE, FALSE, temporary_table, 0) > 0;
+ }
+ if (!temporary_table)
+ {
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ ddl_log.query= { C_STRING_WITH_LEN("DROP_AFTER_CREATE") };
+ ddl_log.org_storage_engine_name= *handler_name;
+ ddl_log.org_partitioned= partitioned;
+ ddl_log.org_database= *db_name;
+ ddl_log.org_table= *table_name;
+ ddl_log.org_table_id= *id;
+ backup_log_ddl(&ddl_log);
+ }
DBUG_RETURN(error);
}
/**
- Quickly remove a table without bin logging
+ Quickly remove a table, without any logging
@param thd Thread context.
@param base The handlerton handle.
@@ -4148,7 +4183,6 @@ int create_table_impl(THD *thd,
int error= 1;
bool frm_only= create_table_mode == C_ALTER_TABLE_FRM_ONLY;
bool internal_tmp_table= create_table_mode == C_ALTER_TABLE || frm_only;
- handlerton *exists_hton;
DBUG_ENTER("create_table_impl");
DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d path: %s",
db.str, table_name.str, internal_tmp_table, path.str));
@@ -4244,10 +4278,12 @@ int create_table_impl(THD *thd,
goto err;
}
- if (!internal_tmp_table && ha_table_exists(thd, &db, &table_name,
- &exists_hton))
+ handlerton *db_type;
+ if (!internal_tmp_table &&
+ ha_table_exists(thd, &db, &table_name,
+ &create_info->org_tabledef_version, NULL, &db_type))
{
- if (ha_check_if_updates_are_ignored(thd, exists_hton, "CREATE"))
+ if (ha_check_if_updates_are_ignored(thd, db_type, "CREATE"))
{
/* Don't create table. CREATE will still be logged in binary log */
error= 0;
@@ -4285,9 +4321,10 @@ int create_table_impl(THD *thd,
thd->variables.option_bits|= OPTION_KEEP_LOG;
thd->log_current_statement= 1;
create_info->table_was_deleted= 1;
+ lex_string_set(&create_info->org_storage_engine_name,
+ ha_resolve_storage_engine_name(db_type));
DBUG_EXECUTE_IF("send_kill_after_delete",
- thd->set_killed(KILL_QUERY); );
-
+ thd->set_killed(KILL_QUERY););
/*
Restart statement transactions for the case of CREATE ... SELECT.
*/
@@ -4305,7 +4342,7 @@ int create_table_impl(THD *thd,
*/
/* Log CREATE IF NOT EXISTS on slave for distributed engines */
- if (thd->slave_thread && (exists_hton && exists_hton->flags &
+ if (thd->slave_thread && (db_type && db_type->flags &
HTON_IGNORE_UPDATES))
thd->log_current_statement= 1;
goto warn;
@@ -4703,6 +4740,19 @@ err:
result= 1;
debug_crash_here("ddl_log_create_after_binlog");
thd->binlog_xid= 0;
+
+ if (!create_info->tmp_table())
+ {
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ ddl_log.query= { C_STRING_WITH_LEN("CREATE") };
+ ddl_log.org_partitioned= (create_info->db_type == partition_hton);
+ ddl_log.org_storage_engine_name= create_info->new_storage_engine_name;
+ ddl_log.org_database= create_table->db;
+ ddl_log.org_table= create_table->table_name;
+ ddl_log.org_table_id= create_info->tabledef_version;
+ backup_log_ddl(&ddl_log);
+ }
}
ddl_log_complete(&ddl_log_state_rm);
ddl_log_complete(&ddl_log_state_create);
@@ -4853,6 +4903,7 @@ bool operator!=(const MYSQL_TIME &lhs, const MYSQL_TIME &rhs)
@param old_name The old table name.
@param new_db The new database name.
@param new_name The new table name.
+ @param id Table version id (for ddl log)
@param flags flags
FN_FROM_IS_TMP old_name is temporary.
FN_TO_IS_TMP new_name is temporary.
@@ -4860,7 +4911,6 @@ bool operator!=(const MYSQL_TIME &lhs, const MYSQL_TIME &rhs)
but only the table in the storage engine.
NO_HA_TABLE Don't rename table in engine.
NO_FK_CHECKS Don't check FK constraints during rename.
-
@return false OK
@return true Error
*/
@@ -4868,7 +4918,7 @@ bool operator!=(const MYSQL_TIME &lhs, const MYSQL_TIME &rhs)
bool
mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
const LEX_CSTRING *old_name, const LEX_CSTRING *new_db,
- const LEX_CSTRING *new_name, uint flags)
+ const LEX_CSTRING *new_name, LEX_CUSTRING *id, uint flags)
{
THD *thd= current_thd;
char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN];
@@ -4877,6 +4927,7 @@ mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
int error=0;
ulonglong save_bits= thd->variables.option_bits;
int length;
+ bool log_query= 0;
DBUG_ENTER("mysql_rename_table");
DBUG_ASSERT(base);
DBUG_PRINT("enter", ("old: '%s'.'%s' new: '%s'.'%s'",
@@ -4914,7 +4965,8 @@ mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
{
if (rename_file_ext(from,to,reg_ext))
error= my_errno;
- if (!(flags & NO_PAR_TABLE))
+ log_query= true;
+ if (file && !(flags & NO_PAR_TABLE))
(void) file->ha_create_partitioning_metadata(to, from, CHF_RENAME_FLAG);
}
else if (!file || likely(!(error=file->ha_rename_table(from_base, to_base))))
@@ -4930,6 +4982,25 @@ mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
file->ha_rename_table(to_base, from_base); // Restore old file name
}
}
+ else
+ log_query= true;
+ }
+ if (!error && log_query && !(flags & (FN_TO_IS_TMP | FN_FROM_IS_TMP)))
+ {
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ ddl_log.query= { C_STRING_WITH_LEN("RENAME") };
+ ddl_log.org_partitioned= file->partition_engine();
+ ddl_log.new_partitioned= ddl_log.org_partitioned;
+ lex_string_set(&ddl_log.org_storage_engine_name, file->real_table_type());
+ ddl_log.org_database= *old_db;
+ ddl_log.org_table= *old_name;
+ ddl_log.org_table_id= *id;
+ ddl_log.new_storage_engine_name= ddl_log.org_storage_engine_name;
+ ddl_log.new_database= *new_db;
+ ddl_log.new_table= *new_name;
+ ddl_log.new_table_id= *id;
+ backup_log_ddl(&ddl_log);
}
delete file;
@@ -4988,6 +5059,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
bool is_trans= FALSE;
bool do_logging= FALSE;
bool force_generated_create= false;
+ bool src_table_exists= FALSE;
uint not_used;
int create_res;
DBUG_ENTER("mysql_create_like_table");
@@ -5021,6 +5093,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
{
/* is_error() may be 0 if table existed and we generated a warning */
res= thd->is_error();
+ src_table_exists= !res;
goto err;
}
/* Ensure we don't try to create something from which we select from */
@@ -5261,7 +5334,6 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
if (write_bin_log(thd, TRUE, query.ptr(), query.length()))
{
res= 1;
- do_logging= 0;
goto err;
}
@@ -5320,6 +5392,9 @@ err:
*/
DBUG_ASSERT(ddl_log_state_rm.is_active());
log_drop_table(thd, &table->db, &table->table_name,
+ &create_info->org_storage_engine_name,
+ create_info->db_type == partition_hton,
+ &create_info->org_tabledef_version,
create_info->tmp_table());
}
else if (res != 2) // Table was not dropped
@@ -5332,6 +5407,18 @@ err:
thd->binlog_xid= 0;
}
+ if (!res && !src_table_exists && !create_info->tmp_table())
+ {
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ ddl_log.query= { C_STRING_WITH_LEN("CREATE") };
+ ddl_log.org_storage_engine_name= local_create_info.new_storage_engine_name;
+ ddl_log.org_database= table->db;
+ ddl_log.org_table= table->table_name;
+ ddl_log.org_table_id= local_create_info.tabledef_version;
+ backup_log_ddl(&ddl_log);
+ }
+
ddl_log_complete(&ddl_log_state_rm);
ddl_log_complete(&ddl_log_state_create);
DBUG_RETURN(res != 0);
@@ -7374,6 +7461,7 @@ static bool mysql_inplace_alter_table(THD *thd,
*/
if (mysql_rename_table(db_type, &alter_ctx->new_db, &alter_ctx->tmp_name,
&alter_ctx->db, &alter_ctx->alias,
+ &alter_ctx->tmp_id,
FN_FROM_IS_TMP | NO_HA_TABLE) ||
thd->is_error())
{
@@ -7388,7 +7476,8 @@ static bool mysql_inplace_alter_table(THD *thd,
DBUG_ASSERT(!tdc_share_is_cached(thd, alter_ctx->db.str,
alter_ctx->table_name.str));
if (mysql_rename_table(db_type, &alter_ctx->db, &alter_ctx->table_name,
- &alter_ctx->new_db, &alter_ctx->new_alias, 0))
+ &alter_ctx->new_db, &alter_ctx->new_alias,
+ &alter_ctx->tmp_id, 0))
{
/*
If the rename fails we will still have a working table
@@ -7411,6 +7500,7 @@ static bool mysql_inplace_alter_table(THD *thd,
(void) mysql_rename_table(db_type,
&alter_ctx->new_db, &alter_ctx->new_alias,
&alter_ctx->db, &alter_ctx->alias,
+ &alter_ctx->id,
NO_FK_CHECKS);
ddl_log_disable_entry(ddl_log_state);
DBUG_RETURN(true);
@@ -8932,13 +9022,30 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
TABLE *table= table_list->table;
MDL_ticket *mdl_ticket= table->mdl_ticket;
DDL_LOG_STATE ddl_log_state;
+ LEX_CSTRING storage_engine;
+ LEX_CUSTRING table_version;
+ uchar table_version_buff[MY_UUID_SIZE];
+ char storage_engine_buff[NAME_LEN];
int error= 0;
+ bool partitioned;
enum ha_extra_function extra_func= thd->locked_tables_mode
? HA_EXTRA_NOT_USED
: HA_EXTRA_FORCE_REOPEN;
DBUG_ENTER("simple_rename_or_index_change");
bzero(&ddl_log_state, sizeof(ddl_log_state));
+ table_version.str= table_version_buff;
+ storage_engine.str= storage_engine_buff;
+ if ((table_version.length= table->s->tabledef_version.length))
+ memcpy((char*) table_version.str, table->s->tabledef_version.str,
+ table_version.length);
+ partitioned= table->file->partition_engine();
+ storage_engine.length= (strmake((char*) storage_engine.str,
+ table->file->real_table_type(),
+ sizeof(storage_engine_buff)-1) -
+ storage_engine.str);
+
+
if (keys_onoff != Alter_info::LEAVE_AS_IS)
{
if (wait_while_table_is_used(thd, table, extra_func))
@@ -8952,6 +9059,18 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
error= alter_table_manage_keys(table,
table->file->indexes_are_disabled(),
keys_onoff);
+ if (table->s->tmp_table == NO_TMP_TABLE)
+ {
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ ddl_log.query= { C_STRING_WITH_LEN("CHANGE_INDEX") };
+ ddl_log.org_storage_engine_name= storage_engine;
+ ddl_log.org_partitioned= partitioned;
+ ddl_log.org_database= table_list->table->s->db;
+ ddl_log.org_table= table_list->table->s->table_name;
+ ddl_log.org_table_id= table_version;
+ backup_log_ddl(&ddl_log);
+ }
}
if (likely(!error) && alter_ctx->is_table_renamed())
@@ -8976,7 +9095,8 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
&alter_ctx->db, &alter_ctx->table_name,
&alter_ctx->new_db, &alter_ctx->new_alias);
if (mysql_rename_table(old_db_type, &alter_ctx->db, &alter_ctx->table_name,
- &alter_ctx->new_db, &alter_ctx->new_alias, 0))
+ &alter_ctx->new_db, &alter_ctx->new_alias,
+ &table_version, 0))
error= -1;
if (!error)
ddl_log_update_phase(&ddl_log_state, DDL_RENAME_PHASE_TRIGGER);
@@ -8992,6 +9112,7 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
(void) mysql_rename_table(old_db_type,
&alter_ctx->new_db, &alter_ctx->new_alias,
&alter_ctx->db, &alter_ctx->table_name,
+ &table_version,
NO_FK_CHECKS);
ddl_log_disable_entry(&ddl_log_state);
error= -1;
@@ -9918,6 +10039,12 @@ do_continue:;
if (unlikely(error))
goto err_cleanup;
+ /* Remember version id for temporary table */
+ alter_ctx.tmp_id= create_info->tabledef_version;
+
+ /* Remember that we have not created table in storage engine yet. */
+ no_ha_table= true;
+
if (alter_info->algorithm(thd) != Alter_info::ALTER_TABLE_ALGORITHM_COPY)
{
Alter_inplace_info ha_alter_info(create_info, alter_info,
@@ -9932,6 +10059,14 @@ do_continue:;
if (fill_alter_inplace_info(thd, table, varchar, &ha_alter_info))
goto err_new_table_cleanup;
+ alter_ctx.tmp_storage_engine_name_partitioned=
+ table->file->partition_engine();
+ alter_ctx.tmp_storage_engine_name.length=
+ (strmake((char*) alter_ctx.tmp_storage_engine_name.str,
+ table->file->real_table_type(),
+ sizeof(alter_ctx.tmp_storage_engine_buff)-1) -
+ alter_ctx.tmp_storage_engine_name.str);
+
/*
We can ignore ALTER_COLUMN_ORDER and instead check
ALTER_STORED_COLUMN_ORDER & ALTER_VIRTUAL_COLUMN_ORDER. This
@@ -10272,6 +10407,15 @@ do_continue:;
goto end_temporary;
}
+ /* Remember storage engine name for the new table */
+ alter_ctx.tmp_storage_engine_name_partitioned=
+ new_table->file->partition_engine();
+ alter_ctx.tmp_storage_engine_name.length=
+ (strmake((char*) alter_ctx.tmp_storage_engine_name.str,
+ new_table->file->real_table_type(),
+ sizeof(alter_ctx.tmp_storage_engine_buff)-1) -
+ alter_ctx.tmp_storage_engine_name.str);
+
/*
Check if file names for the engine are unique. If we change engine
and file names are unique then we don't need to rename the original
@@ -10353,7 +10497,7 @@ do_continue:;
have to do the rename as the table names will not interfer.
*/
if (mysql_rename_table(old_db_type, &alter_ctx.db, &alter_ctx.table_name,
- &alter_ctx.db, &backup_name,
+ &alter_ctx.db, &backup_name, &alter_ctx.id,
FN_TO_IS_TMP |
(engine_changed ? NO_HA_TABLE | NO_PAR_TABLE : 0)))
{
@@ -10386,6 +10530,7 @@ do_continue:;
// Rename the new table to the correct name.
if (mysql_rename_table(new_db_type, &alter_ctx.new_db, &alter_ctx.tmp_name,
&alter_ctx.new_db, &alter_ctx.new_alias,
+ &alter_ctx.tmp_id,
FN_FROM_IS_TMP))
{
// Rename failed, delete the temporary table.
@@ -10397,7 +10542,7 @@ do_continue:;
{
// Restore the backup of the original table to the old name.
(void) mysql_rename_table(old_db_type, &alter_ctx.db, &backup_name,
- &alter_ctx.db, &alter_ctx.alias,
+ &alter_ctx.db, &alter_ctx.alias, &alter_ctx.id,
FN_FROM_IS_TMP | NO_FK_CHECKS |
(engine_changed ? NO_HA_TABLE | NO_PAR_TABLE :
0));
@@ -10422,7 +10567,7 @@ do_continue:;
&alter_ctx.new_db, &alter_ctx.new_alias, 0);
// Restore the backup of the original table to the old name.
(void) mysql_rename_table(old_db_type, &alter_ctx.db, &backup_name,
- &alter_ctx.db, &alter_ctx.alias,
+ &alter_ctx.db, &alter_ctx.alias, &alter_ctx.id,
FN_FROM_IS_TMP | NO_FK_CHECKS |
(engine_changed ? NO_HA_TABLE | NO_PAR_TABLE :
0));
@@ -10506,6 +10651,24 @@ end_inplace:
inplace_alter_table_committed= 0;
}
+ if (!alter_ctx.tmp_table)
+ {
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ ddl_log.query= { C_STRING_WITH_LEN("ALTER") };
+ ddl_log.org_storage_engine_name= alter_ctx.storage_engine_name;
+ ddl_log.org_partitioned= alter_ctx.storage_engine_partitioned;
+ ddl_log.org_database= alter_ctx.db;
+ ddl_log.org_table= alter_ctx.table_name;
+ ddl_log.org_table_id= alter_ctx.id;
+ ddl_log.new_storage_engine_name= alter_ctx.tmp_storage_engine_name;
+ ddl_log.new_partitioned= alter_ctx.tmp_storage_engine_name_partitioned;
+ ddl_log.new_database= alter_ctx.new_db;
+ ddl_log.new_table= alter_ctx.new_alias;
+ ddl_log.new_table_id= alter_ctx.tmp_id;
+ backup_log_ddl(&ddl_log);
+ }
+
table_list->table= NULL; // For query cache
query_cache_invalidate3(thd, table_list, false);
@@ -11228,6 +11391,8 @@ err:
@retval true Engine not available/supported, error has been reported.
@retval false Engine available/supported.
+ create_info->db_type & create_info->new_storage_engine_name
+ are updated.
*/
bool check_engine(THD *thd, const char *db_name,
@@ -11283,6 +11448,8 @@ bool check_engine(THD *thd, const char *db_name,
*new_engine= myisam_hton;
}
+ lex_string_set(&create_info->new_storage_engine_name,
+ ha_resolve_storage_engine_name(*new_engine));
DBUG_RETURN(false);
}
diff --git a/sql/sql_table.h b/sql/sql_table.h
index 0c694eb730c..81894999aac 100644
--- a/sql/sql_table.h
+++ b/sql/sql_table.h
@@ -171,8 +171,8 @@ bool mysql_create_like_table(THD *thd, TABLE_LIST *table,
Table_specification_st *create_info);
bool mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
const LEX_CSTRING *old_name, const LEX_CSTRING *new_db,
- const LEX_CSTRING *new_name, uint flags);
-
+ const LEX_CSTRING *new_name, LEX_CUSTRING *id,
+ uint flags);
bool mysql_backup_table(THD* thd, TABLE_LIST* table_list);
bool mysql_restore_table(THD* thd, TABLE_LIST* table_list);
@@ -189,7 +189,9 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
bool drop_sequence,
bool dont_log_query, bool dont_free_locks);
bool log_drop_table(THD *thd, const LEX_CSTRING *db_name,
- const LEX_CSTRING *table_name, bool temporary_table);
+ const LEX_CSTRING *table_name, const LEX_CSTRING *handler,
+ bool partitioned, const LEX_CUSTRING *id,
+ bool temporary_table);
bool quick_rm_table(THD *thd, handlerton *base, const LEX_CSTRING *db,
const LEX_CSTRING *table_name, uint flags,
const char *table_path=0);
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index c5e112bf8ae..4f6d5c6a1dd 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -673,6 +673,7 @@ end:
if (!result && action_executed)
{
ulonglong save_option_bits= thd->variables.option_bits;
+ backup_log_info ddl_log;
debug_crash_here("ddl_log_drop_before_binlog");
if (add_if_exists_to_binlog)
@@ -684,6 +685,16 @@ end:
thd->binlog_xid= 0;
thd->variables.option_bits= save_option_bits;
debug_crash_here("ddl_log_drop_after_binlog");
+
+ bzero(&ddl_log, sizeof(ddl_log));
+ if (create)
+ ddl_log.query= { C_STRING_WITH_LEN("CREATE") };
+ else
+ ddl_log.query= { C_STRING_WITH_LEN("DROP") };
+ ddl_log.org_storage_engine_name= { C_STRING_WITH_LEN("TRIGGER") };
+ ddl_log.org_database= thd->lex->spname->m_db;
+ ddl_log.org_table= thd->lex->spname->m_name;
+ backup_log_ddl(&ddl_log);
}
ddl_log_complete(&ddl_log_state);
debug_crash_here("ddl_log_drop_before_delete_tmp");
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index 6ab644eb3ce..0f88a159d63 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -192,6 +192,7 @@ Sql_cmd_truncate_table::handler_truncate(THD *thd, TABLE_LIST *table_ref,
{
int error= 0;
uint flags= 0;
+ TABLE *table;
DBUG_ENTER("Sql_cmd_truncate_table::handler_truncate");
/*
@@ -235,10 +236,26 @@ Sql_cmd_truncate_table::handler_truncate(THD *thd, TABLE_LIST *table_ref,
if (fk_truncate_illegal_if_parent(thd, table_ref->table))
DBUG_RETURN(TRUNCATE_FAILED_SKIP_BINLOG);
- error= table_ref->table->file->ha_truncate();
+ table= table_ref->table;
+ error= table->file->ha_truncate();
+
+ if (!is_tmp_table && !error)
+ {
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ ddl_log.query= { C_STRING_WITH_LEN("TRUNCATE") };
+ ddl_log.org_partitioned= table->file->partition_engine();
+ lex_string_set(&ddl_log.org_storage_engine_name,
+ table->file->real_table_type());
+ ddl_log.org_database= table->s->db;
+ ddl_log.org_table= table->s->table_name;
+ ddl_log.org_table_id= table->s->tabledef_version;
+ backup_log_ddl(&ddl_log);
+ }
+
if (unlikely(error))
{
- table_ref->table->file->print_error(error, MYF(0));
+ table->file->print_error(error, MYF(0));
/*
If truncate method is not implemented then we don't binlog the
statement. If truncation has failed in a transactional engine then also
@@ -246,7 +263,7 @@ Sql_cmd_truncate_table::handler_truncate(THD *thd, TABLE_LIST *table_ref,
inspite of errors.
*/
if (error == HA_ERR_WRONG_COMMAND ||
- table_ref->table->file->has_transactions_and_rollback())
+ table->file->has_transactions_and_rollback())
DBUG_RETURN(TRUNCATE_FAILED_SKIP_BINLOG);
else
DBUG_RETURN(TRUNCATE_FAILED_BUT_BINLOG);
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 61a2c43a43f..3fc55552f6b 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -733,6 +733,16 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
thd->binlog_xid= 0;
debug_crash_here("ddl_log_create_after_binlog");
}
+ if (!res)
+ {
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ ddl_log.query= { C_STRING_WITH_LEN("CREATE") };
+ ddl_log.org_storage_engine_name= { C_STRING_WITH_LEN("VIEW") };
+ ddl_log.org_database= view->db;
+ ddl_log.org_table= view->table_name;
+ backup_log_ddl(&ddl_log);
+ }
if (mode != VIEW_CREATE_NEW)
query_cache_invalidate3(thd, view, 0);
@@ -1943,6 +1953,14 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
tdc_remove_table(thd, view->db.str, view->table_name.str);
query_cache_invalidate3(thd, view, 0);
sp_cache_invalidate();
+
+ backup_log_info ddl_log;
+ bzero(&ddl_log, sizeof(ddl_log));
+ ddl_log.query= { C_STRING_WITH_LEN("DROP") };
+ ddl_log.org_storage_engine_name= { C_STRING_WITH_LEN("VIEW") };
+ ddl_log.org_database= view->db;
+ ddl_log.org_table= view->table_name;
+ backup_log_ddl(&ddl_log);
}
something_wrong= (delete_error ||
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc
index 381a84cebf0..e13302d9750 100644
--- a/storage/maria/ha_maria.cc
+++ b/storage/maria/ha_maria.cc
@@ -2314,6 +2314,7 @@ int ha_maria::end_bulk_insert()
BULK_INSERT_SINGLE_UNDO_AND_NO_REPAIR)))
first_error= first_error ? first_error : error;
bulk_insert_single_undo= BULK_INSERT_NONE; // Safety
+ log_not_redoable_operation("BULK_INSERT");
}
can_enable_indexes= 0;
DBUG_RETURN(first_error);
diff --git a/storage/rocksdb/rdb_datadic.cc b/storage/rocksdb/rdb_datadic.cc
index f52d3cee048..6c3e99be55e 100644
--- a/storage/rocksdb/rdb_datadic.cc
+++ b/storage/rocksdb/rdb_datadic.cc
@@ -3793,7 +3793,8 @@ bool Rdb_validate_tbls::check_frm_file(const std::string &fullpath,
*/
char eng_type_buf[NAME_CHAR_LEN+1];
LEX_CSTRING eng_type_str = {eng_type_buf, 0};
- enum Table_type type = dd_frm_type(nullptr, fullfilename.c_ptr(), &eng_type_str);
+ enum Table_type type = dd_frm_type(nullptr, fullfilename.c_ptr(),
+ &eng_type_str, nullptr, nullptr);
if (type == TABLE_TYPE_UNKNOWN) {
// NO_LINT_DEBUG
sql_print_warning("RocksDB: Failed to open/read .from file: %s",