=== added file 'mysql-test/suite/backup/r/backup_duplicate_names.result' === added file 'mysql-test/suite/backup/t/backup_duplicate_names.test' --- mysql-test/suite/backup/t/backup_duplicate_names.test 1970-01-01 00:00:00 +0000 +++ mysql-test/suite/backup/t/backup_duplicate_names.test 2009-09-16 20:31:06 +0000 @@ -0,0 +1,50 @@ +# +# This include file is created to provide +# BLAH BLAH BLAH +# + +--source include/have_case_sensitive_file_system.inc + +--echo # +--echo # Create database and data to test. +--echo # +CREATE DATABASE BACKUP_TEST; + +CREATE DATABASE backup_test; + +CREATE TABLE backup_test.t1 (a char(30)) ENGINE=MEMORY; + +CREATE TABLE backup_test.T1 (a char(30)) ENGINE=MEMORY; + +CREATE PROCEDURE backup_test.p1(p1 CHAR(20)) + INSERT INTO backup_test.t1 VALUES ("50"); + +CREATE PROCEDURE backup_test.P1(p1 CHAR(20)) + INSERT INTO backup_test.t1 VALUES ("51"); + +CREATE TRIGGER backup_test.trg AFTER INSERT ON backup_test.t1 FOR EACH ROW + INSERT INTO backup_test.t1 VALUES('Test objects count'); + +CREATE TRIGGER backup_test.Trg AFTER INSERT ON backup_test.T1 FOR EACH ROW + INSERT INTO backup_test.T1 VALUES('Test objects count'); + +CREATE FUNCTION backup_test.f1() RETURNS INT RETURN (SELECT 1); + +CREATE FUNCTION backup_test.F1() RETURNS INT RETURN (SELECT 2); + +CREATE VIEW backup_test.v1 as SELECT * FROM backup_test.t1; + +CREATE VIEW backup_test.V1 as SELECT * FROM backup_test.T1; + +CREATE EVENT backup_test.e1 ON SCHEDULE EVERY 1 YEAR DO + DELETE FROM backup_test.t1 WHERE a = "not there"; + +CREATE EVENT backup_test.E1 ON SCHEDULE EVERY 1 YEAR DO + DELETE FROM backup_test.T1 WHERE a = "not there"; + +--echo # +--echo # Cleanup +--echo # + +DROP DATABASE BACKUP_TEST; +DROP DATABASE backup_test; \ No newline at end of file === modified file 'sql/backup/image_info.cc' --- sql/backup/image_info.cc 2009-05-21 13:17:37 +0000 +++ sql/backup/image_info.cc 2009-09-16 20:21:08 +0000 @@ -220,6 +220,106 @@ bool Image_info::has_db(const String &db return FALSE; } +/** + Check for duplicate database name. + + This method checks to see if there is another database in the catalog + with the same name either using a case sensitive or case insensitive + compare depending on how lctn was set. + + @param[in] db_name The name of the database to check for + @param[in] db_pos The position in the catalog of the database + + @returns TRUE if duplicate found, FALSE if not found +*/ +bool Image_info::check_duplicate_db_name(const String &db_name, + int db_pos) const +{ + int max_db= m_dbs.count(); + + for (uint db_num=0; db_num < max_db ; db_num++) + if ((db_num != db_pos) && m_dbs[db_num] && + (m_dbs[db_num]->name() == db_name)) + return TRUE; + return FALSE; +} + +/** + Check for duplicate object name. + + This method checks to see if there is another object in the catalog + for the given database with the same name either using a case sensitive + or case insensitive compare dpending on how lctn was set. + + @param[in] type The type of object to look for + @param[in] obj_name The name of the object to check for + @param[in] db_pos The position in the catalog of the database + @param[in] obj_pos The position in the catalog of the database + + @returns TRUE if duplicate found, FALSE if not found + */ +bool Image_info::check_duplicate_obj_name(const enum_bstream_item_type type, + const String &obj_name, + int db_pos, + int obj_pos) const +{ + Db *db= m_dbs[db_pos]; + int max_obj= db->obj_count(); // Maximum number of objects + + for (uint obj_num= 0; obj_num < max_obj; obj_num++) + { + Dbobj *db_obj= db->get_obj(obj_num); + + // Don't compare the same object + if (obj_num == obj_pos) + continue; + + if (db_obj && (db_obj->type() == type) && (db_obj->name() == obj_name)) + return TRUE; + } + return FALSE; +} + + +/** + Check if catalogue contains duplicate objects. + + This method searches the catalog looking for duplicate database names + and within each database if there are duplicate object names based on a + case insensitive search. + + @returns TRUE if duplicate found, FALSE if not found +*/ +bool Image_info::check_for_duplicates() const +{ + int max_db= m_dbs.count(); // Maximum number of databases + + for (uint db_num=0; db_num < max_db ; db_num++) + { + if(m_dbs[db_num]) + { + // First check to see if there is another db with the same name. + if (check_duplicate_db_name(m_dbs[db_num]->name(), db_num)) + return TRUE; + + int max_obj= m_dbs[db_num]->obj_count(); // Max number of objects + + // Now loop through the objects checking to see if there are duplicates. + for (uint obj_num=0; obj_num < max_obj; obj_num++) + { + Dbobj *db_obj= m_dbs[db_num]->get_obj(obj_num); + if (db_obj && check_duplicate_obj_name(db_obj->type(), + db_obj->name(), + db_num, + obj_num)) + return TRUE; + } + } + } + return FALSE; +} + + /** Add per database object to the catalogue. === modified file 'sql/backup/image_info.h' --- sql/backup/image_info.h 2009-09-15 15:02:17 +0000 +++ sql/backup/image_info.h 2009-09-16 20:19:41 +0000 @@ -103,6 +103,14 @@ public: // public interface // Examine contents of the catalogue. bool has_db(const String&) const; + bool check_duplicate_db_name(const String &db_name, + int db_pos) const; + bool check_duplicate_obj_name(const enum_bstream_item_type type, + const String &obj_name, + int db_pos, + int obj_pos) const; + + bool check_for_duplicates() const; // Retrieve objects using their coordinates. === modified file 'sql/backup/kernel.cc' --- sql/backup/kernel.cc 2009-09-10 14:06:46 +0000 +++ sql/backup/kernel.cc 2009-09-16 20:32:02 +0000 @@ -1009,6 +1009,20 @@ Backup_restore_ctx::prepare_for_restore( return NULL; } + /* + Perform a check for duplicate object names in the catalog for a case + insensitive search if the system has the case insensitive setting. + */ + if (lower_case_table_names > 0) + { + bool dupes= info->check_for_duplicates(); + if (dupes || is_killed()) + { + fatal_error(report_error(ER_BACKUP_DUPLICATION_LCTN1)); + return NULL; + } + } + ret= s->next_chunk(); /* Mimic error in next_chunk */ DBUG_EXECUTE_IF("restore_prepare_next_chunk_2", ret= BSTREAM_ERROR; ); === modified file 'sql/share/errmsg-utf8.txt' --- sql/share/errmsg-utf8.txt 2009-09-10 14:06:46 +0000 +++ sql/share/errmsg-utf8.txt 2009-09-16 16:43:14 +0000 @@ -6562,3 +6562,5 @@ ER_BACKUP_ACCESS_OBJS_INCOMPLETE eng "Insufficient privileges. You do not have privileges to backup database '%s'." ER_WARN_I_S_SKIPPED_TABLE eng "Table '%s'.'%s' was skipped since its definition is being modified by concurrent DDL statement." +ER_BACKUP_DUPLICATION_LCTN1 + eng "The backup image contains an objects with case senstive names and the system variable lower_case_table_names is set to 1." === modified file 'sql/share/errmsg.txt' --- sql/share/errmsg.txt 2009-09-10 14:06:46 +0000 +++ sql/share/errmsg.txt 2009-09-16 16:43:14 +0000 @@ -6562,3 +6562,5 @@ ER_BACKUP_ACCESS_OBJS_INCOMPLETE eng "Insufficient privileges. You do not have privileges to backup database '%s'." ER_WARN_I_S_SKIPPED_TABLE eng "Table '%s'.'%s' was skipped since its definition is being modified by concurrent DDL statement." +ER_BACKUP_DUPLICATION_LCTN1 + eng "The backup image contains an objects with case senstive names and the system variable lower_case_table_names is set to 1."