#At file:///localhome/jl208045/mysql/mysql-6.0-backup-34902/
2673 Jorgen Loland 2008-07-30
Bug#34902: "Backup: crash if view depends on dropped object"
Pre-fix behavior: When adding a view to the backup image fails,
the object representing the view is deleted but not removed
from the database catalog. This view object is later tried deleted
as part of catalog delete.
Fix: Add the object and all its dependencies to dependency list
before adding the object to the catalog. If any dependant objects
fail to be added to dep list, the object is not added to the
catalog.
modified:
mysql-test/lib/mtr_report.pl
mysql-test/r/backup_views.result
mysql-test/t/backup_views.test
sql/backup/backup_info.cc
per-file comments:
mysql-test/lib/mtr_report.pl
Views test deliberately triggers error "Backup: Failed to add view..." Ignore this error in the test.
mysql-test/r/backup_views.result
Added results from new test case: backup database with missing view dependencies.
mysql-test/t/backup_views.test
Added test case: backup database with missing view dependencies.
sql/backup/backup_info.cc
In Backup_info::add_db_object
The object is added to catalog after the object and all dependencies have been added to the dependency list. If any of the dependent objects cannot be added to the dep list, the object is not added to the catalog.
=== modified file 'mysql-test/lib/mtr_report.pl'
--- a/mysql-test/lib/mtr_report.pl 2008-07-09 07:12:43 +0000
+++ b/mysql-test/lib/mtr_report.pl 2008-07-30 07:42:08 +0000
@@ -340,6 +340,12 @@ sub mtr_report_stats ($) {
/Restore: Tablespace .* needed by tables being restored has changed on the server/
) or
+ # The views test triggers errors below on purpose
+ ($testname eq 'main.backup_views') and
+ (
+ /Backup: Failed to add view/
+ ) or
+
# ignore warning generated when backup engine selection algorithm is tested
($testname eq 'main.backup_no_be') and /Backup: Cannot create backup engine/ or
# ignore warnings generated when backup privilege is tested
=== modified file 'mysql-test/r/backup_views.result'
--- a/mysql-test/r/backup_views.result 2008-06-12 09:55:35 +0000
+++ b/mysql-test/r/backup_views.result 2008-07-30 07:42:08 +0000
@@ -447,6 +447,55 @@ id name city
6 aa6 RR6
8 aa8 RR8
+*** ENTER Backup of database with missing view dependency should fail but not crash server
+
+initializing test
+DROP DATABASE bup_db1;
+DROP DATABASE bup_db2;
+RESTORE FROM 'bup_objectview.bak';
+backup_id
+#
+USE bup_db1;
+SELECT * FROM t1;
+id name city
+1 aa1 RR1
+2 aa2 RR2
+3 aa3 RR3
+4 aa4 RR4
+5 aa5 RR5
+6 aa6 RR6
+7 aa7 RR7
+8 aa8 RR8
+SELECT * FROM v1;
+id name city
+1 aa1 RR1
+2 aa2 RR2
+3 aa3 RR3
+4 aa4 RR4
+5 aa5 RR5
+6 aa6 RR6
+7 aa7 RR7
+8 aa8 RR8
+DROP TABLE t1;
+
+Testing backup with missing view dependency in same db
+
+SELECT * FROM v1;
+ERROR HY000: View 'bup_db1.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+BACKUP DATABASE bup_db1 TO 'bup_shouldfail1.bak';
+ERROR HY000: Failed to add view `bup_db1`.`v1` to the catalog
+
+Testing backup with missing view dependency in other db
+
+USE bup_db2;
+SELECT * from v3;
+ERROR HY000: View 'bup_db2.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+BACKUP DATABASE bup_db2 TO 'bup_shouldfail2.bak';
+ERROR HY000: Failed to add view `bup_db2`.`v3` to the catalog
+
+*** EXIT Backup of database with missing view dependency
+
+
*** DROP bup_db1, bup_db2 DATABASE ****
DROP DATABASE bup_db1;
=== modified file 'mysql-test/t/backup_views.test'
--- a/mysql-test/t/backup_views.test 2008-06-12 09:55:35 +0000
+++ b/mysql-test/t/backup_views.test 2008-07-30 07:42:08 +0000
@@ -281,6 +281,58 @@ SELECT * FROM v3;
USE bup_db1;
SELECT * FROM t1;
+
+###############
+--echo
+--echo *** ENTER Backup of database with missing view dependency should fail but not crash server
+--echo
+
+--echo initializing test
+
+# start with the backed up database
+DROP DATABASE bup_db1;
+DROP DATABASE bup_db2;
+
+replace_column 1 #;
+RESTORE FROM 'bup_objectview.bak';
+
+# check that table t1 and v1 are initially correct
+USE bup_db1;
+SELECT * FROM t1;
+SELECT * FROM v1;
+
+DROP TABLE t1;
+
+--echo
+--echo Testing backup with missing view dependency in same db
+--echo
+
+# v1 selects from t1, and select now reports error
+--error 1356
+SELECT * FROM v1;
+
+# try to backup - v1 selects from t1 and backup should now fail
+--error 1684
+BACKUP DATABASE bup_db1 TO 'bup_shouldfail1.bak';
+
+--echo
+--echo Testing backup with missing view dependency in other db
+--echo
+
+USE bup_db2;
+--error 1356
+SELECT * from v3;
+
+# try to backup - v3 selects from bup_db1.t1 and backup should now fail
+--error 1684
+BACKUP DATABASE bup_db2 TO 'bup_shouldfail2.bak';
+
+--echo
+--echo *** EXIT Backup of database with missing view dependency
+--echo
+
+###############
+
# Test cleanup section
--echo
@@ -298,4 +350,10 @@ DROP DATABASE bup_db2;
--remove_file $MYSQLTEST_VARDIR/master-data/bup_objectview2.bak
--remove_file $MYSQLTEST_VARDIR/master-data/bup_objectview3.bak
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_shouldfail1.bak
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_shouldfail2.bak
+
#BUG#35249 Mysql server crash for delete operation followed by backup for Default Drivers.
=== modified file 'sql/backup/backup_info.cc'
--- a/sql/backup/backup_info.cc 2008-07-09 07:12:43 +0000
+++ b/sql/backup/backup_info.cc 2008-07-30 07:42:08 +0000
@@ -964,9 +964,9 @@ error:
@param[in] type type of the object
@param[in] obj the object
- The object is also added to the dependency list with @c add_to_dep_list()
- method. If it is a view, its dependencies are handled first using
- @c add_view_deps().
+ The object is added both to the dependency list with @c
+ add_to_dep_list() method and to the catalogue. If it is a view, its
+ dependencies are handled first using @c add_view_deps().
@returns Pointer to @c Image_info::Dbobj instance storing information
about the object or NULL in case of error.
@@ -998,16 +998,6 @@ Backup_info::add_db_object(Db &db, const
}
- Dbobj *o= Image_info::add_db_object(db, type, *name, pos);
-
- if (!o)
- {
- m_ctx.fatal_error(error, db.name().ptr(), name->ptr());
- return NULL;
- }
-
- o->m_obj_ptr= obj;
-
/*
Add new object to the dependency list. If it is a view, add its
dependencies first.
@@ -1026,15 +1016,6 @@ Backup_info::add_db_object(Db &db, const
return NULL;
}
- /*
- Store a pointer to the catalogue item in the dep. list node. If this node
- was a placeholder inserted into the list before, now it will be filled with
- the object we are adding to the catalogue.
- */
-
- DBUG_ASSERT(n);
- n->obj= o;
-
/*
If a new node was created, it must be added to the dependency list with
add_to_dep_list(). However, if the object is a view, we must first add
@@ -1053,6 +1034,36 @@ Backup_info::add_db_object(Db &db, const
add_to_dep_list(type, n);
}
+ /*
+ The object has now been added to the dependancy list. If it is a
+ view, all dependant objects have also been successfully added to
+ the dependency list. The object can now be added to the cataloge
+ and then be linked to from the node in the dep list. Adding to dep
+ list before adding to catalogue ensures that an object will not be
+ added to catalogue if there are problems with it's dependant
+ objects.
+ */
+
+ // Add object to catalogue
+ Dbobj *o= Image_info::add_db_object(db, type, *name, pos);
+
+ if (!o)
+ {
+ m_ctx.fatal_error(error, db.name().ptr(), name->ptr());
+ return NULL;
+ }
+
+ o->m_obj_ptr= obj;
+
+ /*
+ Store a pointer to the catalogue item in the dep. list node. If this node
+ was a placeholder inserted into the list before, now it will be filled with
+ the object we are adding to the catalogue.
+ */
+
+ DBUG_ASSERT(n);
+ n->obj= o;
+
DBUG_PRINT("backup",("Added object %s of type %d from database %s (pos=%lu)",
name->ptr(), type, db.name().ptr(), pos));
return o;