diff options
-rw-r--r-- | mysql-test/extra/binlog_tests/database.test | 35 | ||||
-rw-r--r-- | mysql-test/suite/binlog/r/binlog_database.result | 69 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_drop_db_fail.result | 16 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_drop_db_fail.test | 31 | ||||
-rw-r--r-- | sql/sql_db.cc | 4 |
5 files changed, 150 insertions, 5 deletions
diff --git a/mysql-test/extra/binlog_tests/database.test b/mysql-test/extra/binlog_tests/database.test index d071415bf65..61e8b594185 100644 --- a/mysql-test/extra/binlog_tests/database.test +++ b/mysql-test/extra/binlog_tests/database.test @@ -31,12 +31,47 @@ source include/show_binlog_events.inc; FLUSH STATUS; +--echo +--echo # 'DROP TABLE IF EXISTS <deleted tables>' is binlogged +--echo # when 'DROP DATABASE' fails and at least one table is deleted +--echo # from the database. +RESET MASTER; +CREATE DATABASE testing_1; +USE testing_1; +CREATE TABLE t1(c1 INT); +CREATE TABLE t2(c1 INT); + +let $prefix= `SELECT UUID()`; +--echo # Create a file in the database directory +--replace_result $prefix FAKE_FILE +eval SELECT 'hello' INTO OUTFILE 'fake_file.$prefix'; + +--echo +--echo # 'DROP DATABASE' will fail if there is any other file in the the +--echo # database directory + +# Use '/' instead of '\' in the error message. On windows platform, dir is +# formed with '\'. +--replace_regex /\\testing_1\\*/\/testing_1\// +--error 1010 +DROP DATABASE testing_1; +let $wait_binlog_event= DROP TABLE IF EXIST; +source include/wait_for_binlog_event.inc; +let $MYSQLD_DATADIR= `SELECT @@datadir`; + +--echo +--echo # Remove the fake file. +--remove_file $MYSQLD_DATADIR/testing_1/fake_file.$prefix +--echo # Now we can drop the database. +DROP DATABASE testing_1; + --echo # --echo # Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT --echo # BASED REPLICATION --echo # +USE test; --disable_warnings DROP DATABASE IF EXISTS db1; DROP TABLE IF EXISTS t3; diff --git a/mysql-test/suite/binlog/r/binlog_database.result b/mysql-test/suite/binlog/r/binlog_database.result index 556a23cd7b9..b04d2a09ec6 100644 --- a/mysql-test/suite/binlog/r/binlog_database.result +++ b/mysql-test/suite/binlog/r/binlog_database.result @@ -39,10 +39,31 @@ master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # use `test`; DROP TEMPORARY TABLE `tt1` /* generated by server */ master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */ FLUSH STATUS; + +# 'DROP TABLE IF EXISTS <deleted tables>' is binlogged +# when 'DROP DATABASE' fails and at least one table is deleted +# from the database. +RESET MASTER; +CREATE DATABASE testing_1; +USE testing_1; +CREATE TABLE t1(c1 INT); +CREATE TABLE t2(c1 INT); +# Create a file in the database directory +SELECT 'hello' INTO OUTFILE 'fake_file.FAKE_FILE'; + +# 'DROP DATABASE' will fail if there is any other file in the the +# database directory +DROP DATABASE testing_1; +ERROR HY000: Error dropping database (can't rmdir './testing_1/', errno: 17) + +# Remove the fake file. +# Now we can drop the database. +DROP DATABASE testing_1; # # Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT # BASED REPLICATION # +USE test; DROP DATABASE IF EXISTS db1; DROP TABLE IF EXISTS t3; CREATE DATABASE db1; @@ -58,7 +79,7 @@ Tables_in_db1 t2 show binlog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `db1`; DROP TABLE `t1` +master-bin.000001 # Query # # use `db1`; DROP TABLE IF EXISTS `t1` DROP TABLE t3; DROP DATABASE db1; set binlog_format=mixed; @@ -102,10 +123,31 @@ master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # use `test`; DROP TEMPORARY TABLE `tt1` /* generated by server */ master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */ FLUSH STATUS; + +# 'DROP TABLE IF EXISTS <deleted tables>' is binlogged +# when 'DROP DATABASE' fails and at least one table is deleted +# from the database. +RESET MASTER; +CREATE DATABASE testing_1; +USE testing_1; +CREATE TABLE t1(c1 INT); +CREATE TABLE t2(c1 INT); +# Create a file in the database directory +SELECT 'hello' INTO OUTFILE 'fake_file.FAKE_FILE'; + +# 'DROP DATABASE' will fail if there is any other file in the the +# database directory +DROP DATABASE testing_1; +ERROR HY000: Error dropping database (can't rmdir './testing_1/', errno: 17) + +# Remove the fake file. +# Now we can drop the database. +DROP DATABASE testing_1; # # Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT # BASED REPLICATION # +USE test; DROP DATABASE IF EXISTS db1; DROP TABLE IF EXISTS t3; CREATE DATABASE db1; @@ -121,7 +163,7 @@ Tables_in_db1 t2 show binlog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `db1`; DROP TABLE `t1` +master-bin.000001 # Query # # use `db1`; DROP TABLE IF EXISTS `t1` DROP TABLE t3; DROP DATABASE db1; set binlog_format=row; @@ -166,10 +208,31 @@ master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt1` /* generated by server */ master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */ FLUSH STATUS; + +# 'DROP TABLE IF EXISTS <deleted tables>' is binlogged +# when 'DROP DATABASE' fails and at least one table is deleted +# from the database. +RESET MASTER; +CREATE DATABASE testing_1; +USE testing_1; +CREATE TABLE t1(c1 INT); +CREATE TABLE t2(c1 INT); +# Create a file in the database directory +SELECT 'hello' INTO OUTFILE 'fake_file.FAKE_FILE'; + +# 'DROP DATABASE' will fail if there is any other file in the the +# database directory +DROP DATABASE testing_1; +ERROR HY000: Error dropping database (can't rmdir './testing_1/', errno: 17) + +# Remove the fake file. +# Now we can drop the database. +DROP DATABASE testing_1; # # Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT # BASED REPLICATION # +USE test; DROP DATABASE IF EXISTS db1; DROP TABLE IF EXISTS t3; CREATE DATABASE db1; @@ -185,7 +248,7 @@ Tables_in_db1 t2 show binlog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `db1`; DROP TABLE `t1` +master-bin.000001 # Query # # use `db1`; DROP TABLE IF EXISTS `t1` DROP TABLE t3; DROP DATABASE db1; show databases; diff --git a/mysql-test/suite/rpl/r/rpl_drop_db_fail.result b/mysql-test/suite/rpl/r/rpl_drop_db_fail.result new file mode 100644 index 00000000000..1be90338493 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_drop_db_fail.result @@ -0,0 +1,16 @@ +include/master-slave.inc +[connection master] +CREATE DATABASE IF NOT EXISTS db1; +CREATE DATABASE IF NOT EXISTS db2; +use db1; +CREATE TABLE a(id INT); +CREATE VIEW v AS SELECT * FROM a; +CREATE TABLE table_father(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20)) ENGINE=INNODB; +use db2; +CREATE TABLE table_child(id INT PRIMARY KEY, info VARCHAR(20), father_id INT) ENGINE=INNODB; +ALTER TABLE table_child ADD CONSTRAINT aaa FOREIGN KEY (father_id) REFERENCES db1.table_father(id); +DROP DATABASE db1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +DROP DATABASE db2; +DROP DATABASE db1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_drop_db_fail.test b/mysql-test/suite/rpl/t/rpl_drop_db_fail.test new file mode 100644 index 00000000000..9cf60cf2adf --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_drop_db_fail.test @@ -0,0 +1,31 @@ +############################################################################### +# Bug#20041860: SLAVE ERROR WHEN DROP DATABASE +# +# Test: +# ===== +# Create two databases such that one database has a dependency over the other +# database and try to drop the database which has a dependency. This should +# not cause slave to break. +############################################################################### +--source include/master-slave.inc + +connection master; +CREATE DATABASE IF NOT EXISTS db1; +CREATE DATABASE IF NOT EXISTS db2; + +use db1; +CREATE TABLE a(id INT); +CREATE VIEW v AS SELECT * FROM a; +CREATE TABLE table_father(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20)) ENGINE=INNODB; + +use db2; +CREATE TABLE table_child(id INT PRIMARY KEY, info VARCHAR(20), father_id INT) ENGINE=INNODB; +ALTER TABLE table_child ADD CONSTRAINT aaa FOREIGN KEY (father_id) REFERENCES db1.table_father(id); + +--error ER_ROW_IS_REFERENCED +DROP DATABASE db1; +DROP DATABASE db2; +--sync_slave_with_master +--connection master +DROP DATABASE db1; +--source include/rpl_end.inc diff --git a/sql/sql_db.cc b/sql/sql_db.cc index f4ac6fbbef7..e24d87e849f 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -942,7 +942,7 @@ update_binlog: if (!(query= (char*) thd->alloc(MAX_DROP_TABLE_Q_LEN))) goto exit; /* not much else we can do */ - query_pos= query_data_start= strmov(query,"DROP TABLE "); + query_pos= query_data_start= strmov(query,"DROP TABLE IF EXISTS "); query_end= query + MAX_DROP_TABLE_Q_LEN; db_len= strlen(db); |