#At file:///localhome/jl208045/mysql/mysql-6.0-backup-38624/
2676 Jorgen Loland 2008-08-08
Bug#38624 - Two si_objects.cc functions return 'success'
error code when error occurs.
Pre-fix:
1. DatabaseObj::do_serialize returns 'success' if
check_db_dir_existence returns 'error'
2. TriggerObj::do_serialize returns 'success' if the table the trigger is associated
with cannot be opened.
Fix:
1. Return TRUE ('error') if check_db_dir_existence fails
2. Return TRUE ('error') if open_table fails
modified:
mysql-test/r/backup_errors.result
mysql-test/t/backup_errors.test
sql/backup/kernel.cc
sql/si_objects.cc
per-file comments:
mysql-test/r/backup_errors.result
Added one test case that deletes database after backup started and one that fail to
open table used by a trigger.
mysql-test/t/backup_errors.test
Added one test case that deletes database after backup started and one that fail to
open table used by a trigger.
sql/backup/kernel.cc
Added DBUG_SYNC point right before write_preamble in Backup_restore_ctx::do_backup
sql/si_objects.cc
DatabaseObj::do_serialize and TriggerObj::do_serialize no longer
incorrectly return FALSE ('success') when errors are encountered
=== modified file 'mysql-test/r/backup_errors.result'
--- a/mysql-test/r/backup_errors.result 2008-03-05 17:48:12 +0000
+++ b/mysql-test/r/backup_errors.result 2008-08-08 12:51:06 +0000
@@ -95,3 +95,41 @@ Restoring the table
CREATE TABLE mysql.online_backup_progress LIKE test.obp_copy;
DROP TABLE test.obp_copy;
DROP DATABASE test_ob_error;
+
+Bug#38624
+Test that backup fails with error if database files are removed
+after backup starts
+SET DEBUG_SYNC= 'reset';
+DROP DATABASE IF EXISTS db1;
+CREATE DATABASE db1;
+start backup but stop just before adding metadata to backup image
+SET DEBUG_SYNC= 'backup_before_write_preamble SIGNAL running WAIT_FOR db_will_fail';
+BACKUP DATABASE db1 TO 'bup_db1.bak';
+SET DEBUG_SYNC='now WAIT_FOR running';
+delete database files so that check_db_dir_exists will fail in
+si_objects.cc @ DatabaseObj::do_serialize
+SET DEBUG_SYNC='now SIGNAL db_will_fail';
+Database has been deleted, backup will fail
+ERROR 42000: Unknown database 'db1'
+
+Test that backup fails with error if a table used by
+a trigger cannot be opened
+SET DEBUG_SYNC= 'reset';
+DROP DATABASE IF EXISTS db1;
+CREATE DATABASE db1;
+CREATE TABLE db1.t1 (i int);
+CREATE TABLE db1.t2 (v varchar (20));
+CREATE TRIGGER db1.trg AFTER INSERT ON db1.t1 FOR EACH ROW
+BEGIN
+INSERT INTO db1.t2(v) VALUES ('Test trigger fired');
+END;||
+SET DEBUG_SYNC= 'reset';
+Setting debug point that will make backup fail when adding the
+trigger metadata
+SET SESSION DEBUG='+d,backup_fail_add_trigger';
+BACKUP DATABASE db1 TO 'bup_db1.bak';
+ERROR HY000: Failed to obtain meta-data for trigger `db1`.`trg`
+SET DEBUG_SYNC= 'reset';
+DROP DATABASE db1;
+
+Done testing for Bug#38624
=== modified file 'mysql-test/t/backup_errors.test'
--- a/mysql-test/t/backup_errors.test 2008-03-04 17:09:56 +0000
+++ b/mysql-test/t/backup_errors.test 2008-08-08 12:51:06 +0000
@@ -1,4 +1,6 @@
--source include/not_embedded.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
# Check that BACKUP/RESTORE commands correctly report errors
#
@@ -209,3 +211,82 @@ CREATE TABLE mysql.online_backup_progres
DROP TABLE test.obp_copy;
DROP DATABASE test_ob_error;
+
+
+--echo
+--echo Bug#38624
+--echo Test that backup fails with error if database files are removed
+--echo after backup starts
+
+SET DEBUG_SYNC= 'reset';
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+
+connection con1;
+
+--disable_warnings
+DROP DATABASE IF EXISTS db1;
+
+CREATE DATABASE db1;
+
+connection con2;
+
+--echo start backup but stop just before adding metadata to backup image
+SET DEBUG_SYNC= 'backup_before_write_preamble SIGNAL running WAIT_FOR db_will_fail';
+
+send BACKUP DATABASE db1 TO 'bup_db1.bak';
+
+connection con1;
+
+SET DEBUG_SYNC='now WAIT_FOR running';
+
+--echo delete database files so that check_db_dir_exists will fail in
+--echo si_objects.cc @ DatabaseObj::do_serialize
+
+--remove_file $MYSQLTEST_VARDIR/master-data/db1/db.opt
+--rmdir $MYSQLTEST_VARDIR/master-data/db1
+
+SET DEBUG_SYNC='now SIGNAL db_will_fail';
+
+connection con2;
+--echo Database has been deleted, backup will fail
+--error ER_BAD_DB_ERROR
+reap;
+
+--echo
+--echo Test that backup fails with error if a table used by
+--echo a trigger cannot be opened
+
+SET DEBUG_SYNC= 'reset';
+
+connection con1;
+
+--disable_warnings
+DROP DATABASE IF EXISTS db1;
+
+CREATE DATABASE db1;
+CREATE TABLE db1.t1 (i int);
+CREATE TABLE db1.t2 (v varchar (20));
+
+DELIMITER ||;
+CREATE TRIGGER db1.trg AFTER INSERT ON db1.t1 FOR EACH ROW
+BEGIN
+ INSERT INTO db1.t2(v) VALUES ('Test trigger fired');
+END;||
+DELIMITER ;||
+
+SET DEBUG_SYNC= 'reset';
+
+--echo Setting debug point that will make backup fail when adding the
+--echo trigger metadata
+
+SET SESSION DEBUG='+d,backup_fail_add_trigger';
+--error ER_BACKUP_GET_META_TRIGGER
+BACKUP DATABASE db1 TO 'bup_db1.bak';
+
+SET DEBUG_SYNC= 'reset';
+DROP DATABASE db1;
+
+--echo
+--echo Done testing for Bug#38624
=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc 2008-07-31 10:45:02 +0000
+++ b/sql/backup/kernel.cc 2008-08-08 12:51:06 +0000
@@ -868,6 +868,7 @@ int Backup_restore_ctx::do_backup()
report_stats_pre(info);
DBUG_PRINT("backup",("Writing preamble"));
+ DEBUG_SYNC(m_thd, "backup_before_write_preamble");
if (write_preamble(info, s))
{
=== modified file 'sql/si_objects.cc'
--- a/sql/si_objects.cc 2008-07-09 07:12:43 +0000
+++ b/sql/si_objects.cc 2008-08-08 12:51:06 +0000
@@ -1607,7 +1607,7 @@ bool DatabaseObj::do_serialize(THD *thd,
if (check_db_dir_existence(m_db_name.c_ptr()))
{
my_error(ER_BAD_DB_ERROR, MYF(0), m_db_name.c_ptr());
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(TRUE);
}
load_db_opt_by_name(thd, m_db_name.c_ptr(), &create);
@@ -1938,8 +1938,9 @@ bool TriggerObj::do_serialize(THD *thd,
alloc_mdl_locks(lst, thd->mem_root);
+ DBUG_EXECUTE_IF("backup_fail_add_trigger", DBUG_RETURN(TRUE););
if (open_tables(thd, &lst, &num_tables, 0))
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(TRUE);
DBUG_ASSERT(num_tables == 1);
Table_triggers_list *triggers= lst->table->triggers;