summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/extra/binlog_tests/database.test35
-rw-r--r--mysql-test/suite/binlog/r/binlog_database.result69
-rw-r--r--mysql-test/suite/rpl/r/rpl_drop_db_fail.result16
-rw-r--r--mysql-test/suite/rpl/t/rpl_drop_db_fail.test31
-rw-r--r--sql/sql_db.cc4
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);