List:Commits« Previous MessageNext Message »
From:Rafal Somla Date:December 10 2009 11:24am
Subject:bzr commit into mysql-6.0-backup branch (Rafal.Somla:2903) Bug#43596
View as plain text  
#At file:///ext/mysql/bzr/backup/bug43596/ based on revid:thavamuni.alagu@stripped-108sqz05zrijyp8g

 2903 Rafal Somla	2009-12-10
      BUG#43596 Restore fails on case ins. server for databases who's names 
      differ in case only.
      
      On a case sensitive system such as linux, it is possible to create two 
      server objects whose names differ in letter case only. This is true for 
      databases, tables, views and triggers. When such objects are backed up and 
      then restored on a case insensitive system, they are wrongly treated as a 
      single object which leads to many problems.
      
      This patch modifies RESTORE so that it aborts operation if two server 
      objects with equivalent names are found in the backup image. Each time a new 
      object is added to the catalogue (in bcat_add_item() function) a check is 
      made for possible duplicates. This check is implemented in 
      Image_info::add_X() methods.
      
      Internally, server objects are represented by instances of obs::Obj class 
      from si_objects. This class has methods for reading object's name. A new 
      method is_my_name() is added which checks if a given string is a valid name 
      of the corresponding object. The semantics of this method depends on the 
      system on which it is run (case sensitive vs. case insensitive) and server 
      options setting (such as --lower-case-table-names).
      
      Backup kernel code has been rearranged so that it consequently uses obs::Obj 
      instances to represent server objects. Before, sometimes server objects were 
      referred by their names or by database name, object name pairs. Using 
      obs::Obj instance instead, delegates name handling issues to the si_objects 
      code. For each backed-up/restored server object, an obs::Obj instance is 
      created early in the process and stored in the corresponding entry of the 
      backup/restore catalog. Then obs::Obj methods are used to get the canonical 
      name of the object or to determine if it has an alternative name.
      
      Since we want to create obs::Obj instances before serialization data is 
      available, the obs::get_X() functions are changed so that they can create 
      instances when only server object's name is known. Later, these instances 
      will be updated with the information from serialization string using new 
      obs::Obj::init_from_image() method. After that, the corresponding server 
      object can be created with obs::Obj::create() method as before.
      
      The patch also contains some clean-up in related code areas (see per-file 
      comments).
     @ mysql-test/suite/backup/include/test_for_error.inc
        Mask possibly non-deterministic result here instead of doing it in the code.
     @ mysql-test/suite/backup/std_data/cs_names_d.bkp
        Image with clashing database names.
     @ mysql-test/suite/backup/std_data/cs_names_r.bkp
        Image with clashing trigger names.
     @ mysql-test/suite/backup/std_data/cs_names_t.bkp
        Image with clashing table names.
     @ mysql-test/suite/backup/std_data/cs_names_v.bkp
        Image with clashing view names.
     @ mysql-test/suite/backup/t/backup_cs_names.test
        Test script which creates backup images with clashing object names, to be
        used by backup_cs_names_lctn? tests.
     @ mysql-test/suite/backup/t/backup_cs_names_lctn1.test
        Test restore of clashing object names on lctn=1 system.
     @ mysql-test/suite/backup/t/backup_cs_names_lctn2.test
        Test restore of clashing object names on lctn=2 system.
     @ sql/backup/api_types.h
        Add Db_ref::describe() method, analogous to Table_ref::describe().
     @ sql/backup/backup_info.cc
        - Adapt code to the fact that now add_X() methods expect obs::Obj instance as
          a parameter.
        - Has_db() is replaced by find_db().
        - Fix possible memory leak in error inserted code - delete iterators which have
          been created.
        - Error injection point "ER_BACKUP_CATALOG_ADD_TABLE" is moved to 
          Image_info::add_table(), so that table is *not* added to the catalogue when 
          error is simulated.
        - Move code setting coordinates of trigger's table to 
          Backup_info::add_db_item() because this code should execute only for backup 
          operation.
        - Remove unnecessary dynamic string allocation.
     @ sql/backup/image_info.cc
        - When Image_info::Obj instance is created, it gets a pointer to obs::Obj and 
          assumes ownership of that object. Thus we need special precautions if adding 
          the instance to the catalogue fails.
        - Implementation of find_X() methods.
        - Code handling trigger tables is moved to Backup_info::add_db_object() 
          because it should be executed only during backup operation.
        - Move "ER_BACKUP_CATALOG_ADD_TABLE" error injection point to 
          Image_info::add_table() because we need to report error before we actually 
          create and add to the catalogue the Table instance.
        - Also in Image_info::add_table() move all preparatory actions which can fail, 
          before the moment Table instance is created and added to the catalogue.
     @ sql/backup/image_info.h
        - Add find_ts() function for finding table spaces in the catalogue.
        - Change signatures of add_X() methods so that now they accept obs::Obj 
          parameter.
        - Remove materialize() method which is no longer needed - now obs::Obj 
          instances are required when entries are created in the catalogue.
        - Image_info::Obj() constructor accepts obs::Obj parameter, because each 
          catalogue entry must point at obs::Obj instance.
        - Add initialization method Image_info::Obj::store_info() which fills the 
          basic st_bstream_info members. Object's name is read from obs::Obj 
          instance (and thus is normalized).
        - Make Image_info::Ts inherit from Db_ref, so that code for constructing
          object name can be reused.
        - Add Image_info::Db::find_table/object() methods.
        - Re-use Db_ref::describe() method for Ts and Db classes - avoids code 
          duplication.
     @ sql/backup/kernel.cc
        - For each object added to the catalogue, first an obs::Obj instance must be
          created using obs::get_X() functions. If this fails, error is reported. Once 
          we have obs::Obj instance, it can be added to the catalogue with add_X() 
          method. After that the catalogue assumes ownership of that object and will 
          delete it.
        - When reading metadata, obs::Obj instances stored in catalogue entries are 
          initialized with this data and then objects are created.
        - Avoid unnecessary dynamic string allocation.
        - A possible non-determinism in error messages is resolved in test script,
          not here.
     @ sql/backup/restore_info.h
        - Change signatures of add_X() methods so that now they accept obs::Obj
          parameter.
        - Add checks for duplicates in add_X() methods.
     @ sql/share/errmsg-utf8.txt
        New error messages.
     @ sql/si_objects.cc
        - Implement Obj::is_my_name() method. For databases, tables, views and
          triggers it ignores case if lctn is set.
        - When constructing Obj instances, transform names to lower case if lctn=1.
        - Remove Abstract_obj::init_obj_from_image() which is no longer needed.
        - New implementation of get_X() functions which now do not take serialization 
          string parameter.
     @ sql/si_objects.h
        - Add Obj::is_my_name() method.
        - Add Obj::init_from_image() method.
        - Change signature of get_X() functions - now they dont take serialization
          string as a parameter.

    added:
      mysql-test/suite/backup/r/backup_cs_names.result
      mysql-test/suite/backup/r/backup_cs_names_lctn0.result
      mysql-test/suite/backup/r/backup_cs_names_lctn1.result
      mysql-test/suite/backup/r/backup_cs_names_lctn2.result
      mysql-test/suite/backup/std_data/cs_names_d.bkp
      mysql-test/suite/backup/std_data/cs_names_r.bkp
      mysql-test/suite/backup/std_data/cs_names_t.bkp
      mysql-test/suite/backup/std_data/cs_names_v.bkp
      mysql-test/suite/backup/t/backup_cs_names-master.opt
      mysql-test/suite/backup/t/backup_cs_names.test
      mysql-test/suite/backup/t/backup_cs_names_lctn0.test

      mysql-test/suite/backup/t/backup_cs_names_lctn1-master.opt
      mysql-test/suite/backup/t/backup_cs_names_lctn1.test
      mysql-test/suite/backup/t/backup_cs_names_lctn2-master.opt
      mysql-test/suite/backup/t/backup_cs_names_lctn2.test
    modified:
      mysql-test/suite/backup/include/test_for_error.inc
      sql/backup/api_types.h
      sql/backup/backup_info.cc
      sql/backup/image_info.cc
      sql/backup/image_info.h
      sql/backup/kernel.cc
      sql/backup/restore_info.h
      sql/share/errmsg-utf8.txt
      sql/si_objects.cc
      sql/si_objects.h
=== modified file 'mysql-test/suite/backup/include/test_for_error.inc'
--- a/mysql-test/suite/backup/include/test_for_error.inc	2009-11-24 16:47:23 +0000
+++ b/mysql-test/suite/backup/include/test_for_error.inc	2009-12-10 11:24:07 +0000
@@ -39,7 +39,7 @@ if (`SELECT STRCMP("$operation", "BACKUP
   --echo #
   --disable_abort_on_error
   --replace_column 1 #
-  --replace_regex /Default backup driver|MyISAM backup driver/DEBUG TEST backup driver/
+  --replace_regex /Default backup driver|MyISAM backup driver/DEBUG TEST backup driver/ /Failed to obtain metadata for grant .*/Failed to obtain metadata for grant 'Debug insertion test'./
   # Suppress error numbers if turned on.
   if (`SELECT STRCMP("$suppress", "ON") = 0`)
   {
@@ -67,7 +67,7 @@ if (`SELECT STRCMP("$operation", "RESTOR
   --echo #
   --disable_abort_on_error
   --replace_column 1 # 2 #
-  --replace_regex /Default restore driver|MyISAM restore driver/DEBUG TEST restore driver/
+  --replace_regex /Default restore driver|MyISAM restore driver/DEBUG TEST restore driver/ /Could not execute grant .*/Could not execute grant 'Debug insertion test'./
   RESTORE FROM 'backup_test_orig.bak' OVERWRITE;
   --enable_abort_on_error
 }
@@ -94,7 +94,7 @@ if (`SELECT $my_err = $errno`)
   --echo #
 
   # Mask out error number from select statement.
-  --replace_regex /Default backup driver|MyISAM backup driver/DEBUG TEST backup driver/ /Default restore driver|MyISAM restore driver/DEBUG TEST restore driver/
+  --replace_regex /Default backup driver|MyISAM backup driver/DEBUG TEST backup driver/ /Default restore driver|MyISAM restore driver/DEBUG TEST restore driver/ /Could not execute grant .*/Could not execute grant 'Debug insertion test'./ /Failed to obtain metadata for grant .*/Failed to obtain metadata for grant 'Debug insertion test'./
   --replace_column 1 # 3 ####
   SELECT * FROM mysql.backup_progress WHERE error_num <> 0;
 

=== added file 'mysql-test/suite/backup/r/backup_cs_names.result'
--- a/mysql-test/suite/backup/r/backup_cs_names.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/r/backup_cs_names.result	2009-12-10 11:24:07 +0000
@@ -0,0 +1,61 @@
+CALL mtr.add_suppression("was disabled during restore");
+# Should be 0.
+SELECT @@lower_case_table_names;
+@@lower_case_table_names
+0
+#
+# Create database and objects of various types within it.
+#
+CREATE DATABASE dbA;
+USE dbA;
+CREATE TABLE     tA (a int) COMMENT='upper case name';
+CREATE VIEW      vA AS SELECT 1;
+CREATE TRIGGER   rA AFTER UPDATE ON tA FOR EACH ROW SET @foo=1;
+CREATE EVENT     eA ON SCHEDULE EVERY 1 YEAR DO SET @foo=1;
+CREATE PROCEDURE pA (a int) SET @foo=1;
+CREATE FUNCTION  fA (a int) RETURNS int RETURN a;
+CREATE TABLE     `t��` (b int) COMMENT='upper case accented name';
+CREATE VIEW      `v��` AS SELECT 3;
+CREATE TRIGGER   `r��` AFTER DELETE ON `t��` FOR EACH ROW SET @baz=3;
+CREATE EVENT     `e��` ON SCHEDULE EVERY 1 YEAR DO SET @baz=3;
+CREATE PROCEDURE `p��` (b int) SET @baz=3;
+CREATE FUNCTION  `f��` (b int) RETURNS int RETURN b;
+#
+# Backup database without potential name clashes.
+#
+BACKUP DATABASE dbA TO 'dba.bkp';
+
+# Creating cs_names_d.bkp image.
+CREATE DATABASE dba;
+CREATE TABLE  dba.t1 (b int) COMMENT='in other database';
+BACKUP DATABASE dbA,dba TO 'cs_names_d.bkp';
+
+# Creating cs_names_t.bkp image.
+USE dbA;
+CREATE TABLE ta (c char) COMMENT='lower case name';
+BACKUP DATABASE dbA TO 'cs_names_t.bkp';
+
+# Creating cs_names_v.bkp image.
+RESTORE FROM 'dba.bkp' OVERWRITE;
+USE dbA;
+CREATE VIEW va AS SELECT 2;
+BACKUP DATABASE dbA TO 'cs_names_v.bkp';
+
+# Creating cs_names_r.bkp image.
+RESTORE FROM 'dba.bkp' OVERWRITE;
+USE dbA;
+CREATE TRIGGER ra BEFORE DELETE ON tA FOR EACH ROW SET @bar=2;
+BACKUP DATABASE dbA TO 'cs_names_r.bkp';
+
+# Checking stored procedures and events.
+USE dbA;
+CREATE EVENT ea ON SCHEDULE EVERY 1 YEAR DO SET @bar=2;
+ERROR HY000: Event 'ea' already exists
+CREATE PROCEDURE pa (a int) SET @bar=2;
+ERROR 42000: PROCEDURE pa already exists
+CREATE FUNCTION fa (a int) RETURNS int RETURN 1;
+ERROR 42000: FUNCTION fa already exists
+
+# Cleanup.
+DROP DATABASE dbA;
+DROP DATABASE dba;

=== added file 'mysql-test/suite/backup/r/backup_cs_names_lctn0.result'
--- a/mysql-test/suite/backup/r/backup_cs_names_lctn0.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/r/backup_cs_names_lctn0.result	2009-12-10 11:24:07 +0000
@@ -0,0 +1,33 @@
+CALL mtr.add_suppression("was disabled during restore");
+# Should be 0.
+SELECT @@lower_case_table_names;
+@@lower_case_table_names
+0
+
+# Restoring from cs_names_d.bkp image.
+RESTORE FROM 'cs_names_d.bkp' OVERWRITE;
+backup_id
+###
+Warnings:
+###	###	The event 'dbA.eA' was disabled during restore.
+
+# Restoring from cs_names_t.bkp image.
+RESTORE FROM 'cs_names_t.bkp' OVERWRITE;
+backup_id
+###
+Warnings:
+###	###	The event 'dbA.eA' was disabled during restore.
+
+# Restoring from cs_names_v.bkp image.
+RESTORE FROM 'cs_names_v.bkp' OVERWRITE;
+backup_id
+###
+
+# Restoring from cs_names_r.bkp image.
+RESTORE FROM 'cs_names_r.bkp' OVERWRITE;
+backup_id
+###
+
+# Cleanup.
+DROP DATABASE IF EXISTS dbA;
+DROP DATABASE IF EXISTS dba;

=== added file 'mysql-test/suite/backup/r/backup_cs_names_lctn1.result'
--- a/mysql-test/suite/backup/r/backup_cs_names_lctn1.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/r/backup_cs_names_lctn1.result	2009-12-10 11:24:07 +0000
@@ -0,0 +1,41 @@
+CALL mtr.add_suppression("was disabled during restore");
+CALL mtr.add_suppression("Restore: Backup image contains two objects named");
+SELECT @@lower_case_table_names;
+@@lower_case_table_names
+1
+
+# Restoring from cs_names_d.bkp image.
+RESTORE FROM 'cs_names_d.bkp' OVERWRITE;
+ERROR HY000: Backup image contains two objects named 'dba'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+SHOW WARNINGS;
+Level	Code	Message
+Error	###	Backup image contains two objects named 'dba'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+Warning	###	Operation aborted
+
+# Restoring from cs_names_t.bkp image.
+RESTORE FROM 'cs_names_t.bkp' OVERWRITE;
+ERROR HY000: Backup image contains two objects named 'ta' in database 'dba'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+SHOW WARNINGS;
+Level	Code	Message
+Error	###	Backup image contains two objects named 'ta' in database 'dba'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+Warning	###	Operation aborted
+
+# Restoring from cs_names_v.bkp image.
+RESTORE FROM 'cs_names_v.bkp' OVERWRITE;
+ERROR HY000: Backup image contains two objects named 'vA' in database 'dba'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+SHOW WARNINGS;
+Level	Code	Message
+Error	###	Backup image contains two objects named 'vA' in database 'dba'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+Warning	###	Operation aborted
+
+# Restoring from cs_names_r.bkp image.
+RESTORE FROM 'cs_names_r.bkp' OVERWRITE;
+ERROR HY000: Backup image contains two objects named 'rA' in database 'dba'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+SHOW WARNINGS;
+Level	Code	Message
+Error	###	Backup image contains two objects named 'rA' in database 'dba'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+Warning	###	Operation aborted
+
+# Cleanup.
+DROP DATABASE IF EXISTS dbA;
+DROP DATABASE IF EXISTS dba;

=== added file 'mysql-test/suite/backup/r/backup_cs_names_lctn2.result'
--- a/mysql-test/suite/backup/r/backup_cs_names_lctn2.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/r/backup_cs_names_lctn2.result	2009-12-10 11:24:07 +0000
@@ -0,0 +1,41 @@
+CALL mtr.add_suppression("was disabled during restore");
+CALL mtr.add_suppression("Restore: Backup image contains two objects named");
+SELECT @@lower_case_table_names;
+@@lower_case_table_names
+2
+
+# Restoring from cs_names_d.bkp image.
+RESTORE FROM 'cs_names_d.bkp' OVERWRITE;
+ERROR HY000: Backup image contains two objects named 'dbA'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+SHOW WARNINGS;
+Level	Code	Message
+Error	###	Backup image contains two objects named 'dbA'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+Warning	###	Operation aborted
+
+# Restoring from cs_names_t.bkp image.
+RESTORE FROM 'cs_names_t.bkp' OVERWRITE;
+ERROR HY000: Backup image contains two objects named 'tA' in database 'dbA'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+SHOW WARNINGS;
+Level	Code	Message
+Error	###	Backup image contains two objects named 'tA' in database 'dbA'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+Warning	###	Operation aborted
+
+# Restoring from cs_names_v.bkp image.
+RESTORE FROM 'cs_names_v.bkp' OVERWRITE;
+ERROR HY000: Backup image contains two objects named 'vA' in database 'dbA'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+SHOW WARNINGS;
+Level	Code	Message
+Error	###	Backup image contains two objects named 'vA' in database 'dbA'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+Warning	###	Operation aborted
+
+# Restoring from cs_names_r.bkp image.
+RESTORE FROM 'cs_names_r.bkp' OVERWRITE;
+ERROR HY000: Backup image contains two objects named 'rA' in database 'dbA'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+SHOW WARNINGS;
+Level	Code	Message
+Error	###	Backup image contains two objects named 'rA' in database 'dbA'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1.
+Warning	###	Operation aborted
+
+# Cleanup.
+DROP DATABASE IF EXISTS dbA;
+DROP DATABASE IF EXISTS dba;

=== added file 'mysql-test/suite/backup/std_data/cs_names_d.bkp'
Binary files a/mysql-test/suite/backup/std_data/cs_names_d.bkp	1970-01-01 00:00:00 +0000 and b/mysql-test/suite/backup/std_data/cs_names_d.bkp	2009-12-10 11:24:07 +0000 differ

=== added file 'mysql-test/suite/backup/std_data/cs_names_r.bkp'
Binary files a/mysql-test/suite/backup/std_data/cs_names_r.bkp	1970-01-01 00:00:00 +0000 and b/mysql-test/suite/backup/std_data/cs_names_r.bkp	2009-12-10 11:24:07 +0000 differ

=== added file 'mysql-test/suite/backup/std_data/cs_names_t.bkp'
Binary files a/mysql-test/suite/backup/std_data/cs_names_t.bkp	1970-01-01 00:00:00 +0000 and b/mysql-test/suite/backup/std_data/cs_names_t.bkp	2009-12-10 11:24:07 +0000 differ

=== added file 'mysql-test/suite/backup/std_data/cs_names_v.bkp'
Binary files a/mysql-test/suite/backup/std_data/cs_names_v.bkp	1970-01-01 00:00:00 +0000 and b/mysql-test/suite/backup/std_data/cs_names_v.bkp	2009-12-10 11:24:07 +0000 differ

=== added file 'mysql-test/suite/backup/t/backup_cs_names-master.opt'
--- a/mysql-test/suite/backup/t/backup_cs_names-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_cs_names-master.opt	2009-12-10 11:24:07 +0000
@@ -0,0 +1 @@
+--lower-case-table-names=0

=== added file 'mysql-test/suite/backup/t/backup_cs_names.test'
--- a/mysql-test/suite/backup/t/backup_cs_names.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_cs_names.test	2009-12-10 11:24:07 +0000
@@ -0,0 +1,125 @@
+#
+# Check how RESTORE handles objects whose names differ in case only
+# on a case insensitive system.
+#
+# This test script creates backup images which contain objects of different
+# types whose names might clash on case insensitive system:
+#
+# - cs_names_d.bkp: clash in database names
+# - cs_names_t.bkp: clash in table names
+# - cs_names_v.bkp: clash in view names
+# - cs_names_r.bkp: clash in trigger name
+#
+# Note that for other types of objects supported by backup (stored routines, 
+# events) it is not possible to create two objects whose names differ in
+# case only, even on case sensitive system with lctn=0.
+#
+# The images are committed to suite/backup/std_data/ directory where other tests
+# are looking for them. However, this test stores newly generated images in 
+# var/run/ directory. This is so that new images do not immediately overwrite
+# old ones.
+#
+# If required (e.g., format of the backup image changes), then images generated
+# by this script should be manually moved to suite/backup/std_data and 
+# re-committed.
+#
+--source include/not_embedded.inc
+--source include/not_windows.inc
+
+CALL mtr.add_suppression("was disabled during restore");
+
+--echo # Should be 0.
+SELECT @@lower_case_table_names;
+
+--disable_result_log
+
+let $imgdir= $MYSQLTEST_VARDIR/run;
+let $bdir=`select @@backupdir`;
+
+--echo #
+--echo # Create database and objects of various types within it.
+--echo #
+CREATE DATABASE dbA;
+USE dbA;
+CREATE TABLE     tA (a int) COMMENT='upper case name';
+CREATE VIEW      vA AS SELECT 1;
+CREATE TRIGGER   rA AFTER UPDATE ON tA FOR EACH ROW SET @foo=1;
+CREATE EVENT     eA ON SCHEDULE EVERY 1 YEAR DO SET @foo=1;
+CREATE PROCEDURE pA (a int) SET @foo=1;
+CREATE FUNCTION  fA (a int) RETURNS int RETURN a;
+
+#
+# Add objects with letter '��' which is equivalent to 'A' according to case 
+# insensitive collations. This is to see that it would not cause any name 
+# clashes.
+#
+
+CREATE TABLE     `t��` (b int) COMMENT='upper case accented name';
+CREATE VIEW      `v��` AS SELECT 3;
+CREATE TRIGGER   `r��` AFTER DELETE ON `t��` FOR EACH ROW SET @baz=3;
+CREATE EVENT     `e��` ON SCHEDULE EVERY 1 YEAR DO SET @baz=3;
+CREATE PROCEDURE `p��` (b int) SET @baz=3;
+CREATE FUNCTION  `f��` (b int) RETURNS int RETURN b;
+
+--echo #
+--echo # Backup database without potential name clashes.
+--echo #
+BACKUP DATABASE dbA TO 'dba.bkp';
+

+--echo 
+--echo # Creating cs_names_d.bkp image.
+--error 0,1
+--remove_file $imgdir/cs_names_d.bkp
+CREATE DATABASE dba;
+CREATE TABLE  dba.t1 (b int) COMMENT='in other database';
+BACKUP DATABASE dbA,dba TO 'cs_names_d.bkp';
+--move_file $bdir/cs_names_d.bkp $imgdir/cs_names_d.bkp
+
+--echo 
+--echo # Creating cs_names_t.bkp image.
+--error 0,1
+--remove_file $imgdir/cs_names_t.bkp
+USE dbA;
+CREATE TABLE ta (c char) COMMENT='lower case name';
+BACKUP DATABASE dbA TO 'cs_names_t.bkp';
+--move_file $bdir/cs_names_t.bkp $imgdir/cs_names_t.bkp
+
+--echo 
+--echo # Creating cs_names_v.bkp image.
+--error 0,1
+--remove_file $imgdir/cs_names_v.bkp
+# Restore original database without name clashes.
+RESTORE FROM 'dba.bkp' OVERWRITE;
+USE dbA;
+CREATE VIEW va AS SELECT 2;
+BACKUP DATABASE dbA TO 'cs_names_v.bkp';
+--move_file $bdir/cs_names_v.bkp $imgdir/cs_names_v.bkp
+
+--echo 
+--echo # Creating cs_names_r.bkp image.
+--error 0,1
+--remove_file $imgdir/cs_names_r.bkp
+# Restore original database without name clashes.
+RESTORE FROM 'dba.bkp' OVERWRITE;
+USE dbA;
+CREATE TRIGGER ra BEFORE DELETE ON tA FOR EACH ROW SET @bar=2;
+BACKUP DATABASE dbA TO 'cs_names_r.bkp';
+--move_file $bdir/cs_names_r.bkp $imgdir/cs_names_r.bkp
+
+--echo 
+--echo # Checking stored procedures and events.
+--enable_result_log
+USE dbA;
+--error ER_EVENT_ALREADY_EXISTS
+CREATE EVENT ea ON SCHEDULE EVERY 1 YEAR DO SET @bar=2;
+--error ER_SP_ALREADY_EXISTS
+CREATE PROCEDURE pa (a int) SET @bar=2;
+--error ER_SP_ALREADY_EXISTS
+CREATE FUNCTION fa (a int) RETURNS int RETURN 1;
+
+--echo 
+--echo # Cleanup.
+DROP DATABASE dbA;
+DROP DATABASE dba;
+--exit
+ 

=== added file 'mysql-test/suite/backup/t/backup_cs_names_lctn0.test'
--- a/mysql-test/suite/backup/t/backup_cs_names_lctn0.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_cs_names_lctn0.test	2009-12-10 11:24:07 +0000
@@ -0,0 +1,63 @@
+#
+# Check that on a case sensitive system one can correctly restore image 
+# containing objects whose names would clash on case insensitive system.
+#
+# This test script uses backup images created by backup_cs_names script:
+#
+# - cs_names_d.bkp: clash in database names
+# - cs_names_t.bkp: clash in table names
+# - cs_names_v.bkp: clash in view names
+# - cs_names_r.bkp: clash in trigger name
+#
+# The images are stored in suite/backup/std_data/ directory. For simplicity,
+# we copy them first to the standard backup location
+#
+# Note: When backup image format changes these backup images must be 
+# re-generated and re-committed.
+#
+--source include/not_embedded.inc
+
+CALL mtr.add_suppression("was disabled during restore");
+
+--echo # Should be 0.
+SELECT @@lower_case_table_names;
+
+let $imgdir= suite/backup/std_data;
+let $bdir=`select @@backupdir`;
+
+#
+# Note: if these statements fail then perhaps backup images are missing. They
+# should be re-generated using backup_cs_names test.
+#
+--copy_file $imgdir/cs_names_d.bkp $bdir/cs_names_d.bkp
+--copy_file $imgdir/cs_names_t.bkp $bdir/cs_names_t.bkp
+--copy_file $imgdir/cs_names_v.bkp $bdir/cs_names_v.bkp
+--copy_file $imgdir/cs_names_r.bkp $bdir/cs_names_r.bkp
+
+--echo 
+--echo # Restoring from cs_names_d.bkp image.
+--replace_column 1 ### 2 ###
+RESTORE FROM 'cs_names_d.bkp' OVERWRITE;
+
+--echo 
+--echo # Restoring from cs_names_t.bkp image.
+--replace_column 1 ### 2 ###
+RESTORE FROM 'cs_names_t.bkp' OVERWRITE;
+
+--echo 
+--echo # Restoring from cs_names_v.bkp image.
+--replace_column 1 ### 2 ###
+RESTORE FROM 'cs_names_v.bkp' OVERWRITE;
+
+--echo 
+--echo # Restoring from cs_names_r.bkp image.
+--replace_column 1 ### 2 ###
+RESTORE FROM 'cs_names_r.bkp' OVERWRITE;
+
+--echo 
+--echo # Cleanup.
+--disable_warnings
+DROP DATABASE IF EXISTS dbA;
+DROP DATABASE IF EXISTS dba;
+--exit
+ 

=== added file 'mysql-test/suite/backup/t/backup_cs_names_lctn1-master.opt'
--- a/mysql-test/suite/backup/t/backup_cs_names_lctn1-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_cs_names_lctn1-master.opt	2009-12-10 11:24:07 +0000
@@ -0,0 +1 @@
+--lower-case-table-names=1

=== added file 'mysql-test/suite/backup/t/backup_cs_names_lctn1.test'
--- a/mysql-test/suite/backup/t/backup_cs_names_lctn1.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_cs_names_lctn1.test	2009-12-10 11:24:07 +0000
@@ -0,0 +1,74 @@
+#
+# Check how RESTORE handles objects whose names differ in case only
+# on a case insensitive system.
+#
+# This test script uses backup images created by backup_cs_names script:
+#
+# - cs_names_d.bkp: clash in database names
+# - cs_names_t.bkp: clash in table names
+# - cs_names_v.bkp: clash in view names
+# - cs_names_r.bkp: clash in trigger name
+#
+# It restores from each image and checks that correct error is reported in 
+# each case.
+#
+# The images are stored in suite/backup/std_data/ directory. For simplicity,
+# we copy them first to the standard backup location
+#
+# Note: When backup image format changes these backup images must be 
+# re-generated and re-committed.
+#
+--source include/not_embedded.inc
+
+CALL mtr.add_suppression("was disabled during restore");
+CALL mtr.add_suppression("Restore: Backup image contains two objects named");
+
+SELECT @@lower_case_table_names;
+
+let $imgdir= suite/backup/std_data;
+let $bdir=`select @@backupdir`;
+
+#
+# Note: if these statements fail then perhaps backup images are missing. They
+# should be re-generated using backup_cs_names test.
+#
+--copy_file $imgdir/cs_names_d.bkp $bdir/cs_names_d.bkp
+--copy_file $imgdir/cs_names_t.bkp $bdir/cs_names_t.bkp
+--copy_file $imgdir/cs_names_v.bkp $bdir/cs_names_v.bkp
+--copy_file $imgdir/cs_names_r.bkp $bdir/cs_names_r.bkp
+
+--echo 
+--echo # Restoring from cs_names_d.bkp image.
+--error ER_RESTORE_NONUNIQ_OBJECT
+RESTORE FROM 'cs_names_d.bkp' OVERWRITE;
+--replace_column 2 ###
+SHOW WARNINGS;
+
+--echo 
+--echo # Restoring from cs_names_t.bkp image.
+--error ER_RESTORE_NONUNIQ_DBOBJECT
+RESTORE FROM 'cs_names_t.bkp' OVERWRITE;
+--replace_column 2 ###
+SHOW WARNINGS;
+
+--echo 
+--echo # Restoring from cs_names_v.bkp image.
+--error ER_RESTORE_NONUNIQ_DBOBJECT
+RESTORE FROM 'cs_names_v.bkp' OVERWRITE;
+--replace_column 2 ###
+SHOW WARNINGS;
+
+--echo 
+--echo # Restoring from cs_names_r.bkp image.
+--error ER_RESTORE_NONUNIQ_DBOBJECT
+RESTORE FROM 'cs_names_r.bkp' OVERWRITE;
+--replace_column 2 ###
+SHOW WARNINGS;
+
+--echo 
+--echo # Cleanup.
+--disable_warnings
+DROP DATABASE IF EXISTS dbA;
+DROP DATABASE IF EXISTS dba;
+--exit
+ 

=== added file 'mysql-test/suite/backup/t/backup_cs_names_lctn2-master.opt'
--- a/mysql-test/suite/backup/t/backup_cs_names_lctn2-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_cs_names_lctn2-master.opt	2009-12-10 11:24:07 +0000
@@ -0,0 +1 @@
+--lower-case-table-names=2

=== added file 'mysql-test/suite/backup/t/backup_cs_names_lctn2.test'
--- a/mysql-test/suite/backup/t/backup_cs_names_lctn2.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_cs_names_lctn2.test	2009-12-10 11:24:07 +0000
@@ -0,0 +1,3 @@
+--source include/not_embedded.inc
+--source include/have_case_insensitive_file_system.inc
+--source suite/backup/t/backup_cs_names_lctn1.test

=== modified file 'sql/backup/api_types.h'
--- a/sql/backup/api_types.h	2009-12-01 01:49:23 +0000
+++ b/sql/backup/api_types.h	2009-12-10 11:24:07 +0000
@@ -105,6 +105,15 @@ public:
   bool operator!=(const Db_ref &db) const
   { return ! this->operator == (db); }
 
+  /// Definition of a name buffer for the database name.
+  typedef char name_buf[FN_REFLEN];
+
+  /// Produce string identifying the database (e.g. for error reporting).
+  const char* describe(char *buf, size_t len) const;
+  /// Produce string identifying the database (e.g. for error reporting).
+  const char* describe(name_buf &buf) const
+  { return describe(buf, sizeof(buf)); }
+
 protected:
 
   // Constructors are made protected as clients of this class are

=== modified file 'sql/backup/backup_info.cc'
--- a/sql/backup/backup_info.cc	2009-12-01 01:49:23 +0000
+++ b/sql/backup/backup_info.cc	2009-12-10 11:24:07 +0000
@@ -667,7 +667,7 @@ backup::Image_info::Ts* Backup_info::add
 
   ulong pos= ts_count();
 
-  Ts *ts= Image_info::add_ts(*name, pos);
+  Ts *ts= Image_info::add_ts(obj, pos);
 
   if (!ts)
   {
@@ -675,10 +675,6 @@ backup::Image_info::Ts* Backup_info::add
     return NULL;
   }
 
-  // Store pointer to the server object instance.
-
-  ts->m_obj_ptr= obj;
-
   // Add new entry to ts_hash.
 
   n1= new Ts_hash_node(n0);
@@ -759,7 +755,7 @@ backup::Image_info::Db* Backup_info::add
     return NULL;
   }
 
-  Db *db= Image_info::add_db(*name, pos);
+  Db *db= Image_info::add_db(obj, pos);
 
   if (!db)
   {
@@ -767,8 +763,6 @@ backup::Image_info::Db* Backup_info::add
     return NULL;
   }
 
-  db->m_obj_ptr= obj;
-
   return db;
 }
 
@@ -831,7 +825,7 @@ int Backup_info::add_dbs(THD *thd, List<
     db_name= obj->get_db_name()->ptr();
 
     // Error if the same database is requested twice in the database list.
-    if (has_db(db_name))
+    if (find_db(db_name))
     {
       m_log.report_error(ER_NONUNIQ_DB, db_name.c_ptr());;
       delete obj;
@@ -901,7 +895,7 @@ int Backup_info::add_all_dbs()
   Obj_iterator *dbit= get_databases(m_thd);
 
   // Error code insertion for ER_BACKUP_LIST_DBS.
-  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DBS", dbit= 0;);
+  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DBS", { delete dbit; dbit= NULL; };);
 
   if (!dbit)
   {
@@ -994,7 +988,7 @@ int Backup_info::add_db_items(Db &db)
   Obj_iterator *it= get_db_tables(m_thd, &db.name());
 
   // Error code insertion for ER_BACKUP_LIST_DB_TABLES.
-  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DB_TABLES", it= 0;);
+  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DB_TABLES", { delete it; it= NULL; };);
 
   if (!it)
   {
@@ -1045,7 +1039,7 @@ int Backup_info::add_db_items(Db &db)
   it= get_db_stored_procedures(m_thd, &db.name());
 
   // Error code insertion for ER_BACKUP_LIST_DB_SROUT.
-  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DB_SROUT_P", it= 0;);
+  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DB_SROUT_P", { delete it; it= NULL; };);
 
   if (!it)
   {
@@ -1060,7 +1054,7 @@ int Backup_info::add_db_items(Db &db)
   it= get_db_stored_functions(m_thd, &db.name());
 
   // Error code insertion for ER_BACKUP_LIST_DB_SROUT.
-  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DB_SROUT_F", it= 0;);
+  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DB_SROUT_F", { delete it; it= NULL; };);
 
   if (!it)
   {
@@ -1075,7 +1069,7 @@ int Backup_info::add_db_items(Db &db)
   it= get_db_views(m_thd, &db.name());
 
   // Error code insertion for ER_BACKUP_LIST_DB_VIEWS.
-  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DB_VIEWS", it= 0;);
+  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DB_VIEWS", { delete it; it= NULL; };);
 
   if (!it)
   {
@@ -1090,7 +1084,7 @@ int Backup_info::add_db_items(Db &db)
   it= get_db_events(m_thd, &db.name());
 
   // Error code insertion for ER_BACKUP_LIST_DB_EVENTS.
-  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DB_EVENTS", it= 0;);
+  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DB_EVENTS", { delete it; it= NULL; };);
 
   if (!it)
   {
@@ -1105,7 +1099,7 @@ int Backup_info::add_db_items(Db &db)
   it= get_db_triggers(m_thd, &db.name());
 
   // Error code insertion for ER_BACKUP_LIST_DB_TRIGGERS.
-  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DB_TRIGGERS", it= 0;);
+  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DB_TRIGGERS", { delete it; it= NULL; };);
 
   if (!it)
   {
@@ -1120,7 +1114,7 @@ int Backup_info::add_db_items(Db &db)
   it= get_all_db_grants(m_thd, &db.name());
 
   // Error code insertion for ER_BACKUP_LIST_DB_PRIV.
-  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DB_PRIV", it= 0;);
+  DBUG_EXECUTE_IF("ER_BACKUP_LIST_DB_PRIV", { delete it; it= NULL; };);
 
   if (!it)
   {
@@ -1201,10 +1195,7 @@ backup::Image_info::Table* Backup_info::
 
   ulong pos= snap->table_count();
 
-  tbl= Image_info::add_table(dbi, t.name(), *snap, pos);
-
-  // Error code insertion for ER_BACKUP_CATALOG_ADD_TABLE.
-  DBUG_EXECUTE_IF("ER_BACKUP_CATALOG_ADD_TABLE", tbl= 0;);
+  tbl= Image_info::add_table(dbi, obj, *snap, pos);
 
   if (!tbl)
   {
@@ -1213,8 +1204,6 @@ backup::Image_info::Table* Backup_info::
     return NULL;
   }
 
-  tbl->m_obj_ptr= obj;
-
   DBUG_PRINT("backup",(" table %s backed-up with %s engine (snapshot %d)",
                       t.name().ptr(), snap->name(), snap->m_num));
   return tbl;
@@ -1356,6 +1345,8 @@ Backup_info::add_db_object(Db &db, const
 {
   int error= 0;
   ulong pos= db.obj_count();
+  /// Points at trigger's table, if we insert a trigger.
+  Table *trg_table= NULL;
 
   DBUG_ASSERT(obj);
   DBUG_ASSERT(obj->get_name());
@@ -1379,6 +1370,45 @@ Backup_info::add_db_object(Db &db, const
   }
 
   /*
+    If this is a trigger, get the table for the trigger. If we fail here,
+    we abort operation without inserting the object into the catalog.
+  */
+  if (type == BSTREAM_IT_TRIGGER)
+  {
+    THD *thd= ::current_thd;
+    obs::Obj *tbl_obj= obs::find_table_for_trigger(thd, &db.name(), 
+                                                        obj->get_name());
+    DBUG_EXECUTE_IF("ER_BACKUP_CATALOG_ADD_TRIGGER_1", 
+                    { delete tbl_obj; tbl_obj= NULL; };);
+    if (!tbl_obj)
+    {
+      // TODO: Consider more specific error message.
+      m_log.report_error(error, db.name().ptr(), obj->get_name()->ptr());
+      return NULL;
+    }
+    
+    Db *db_found= find_db(db.name());
+
+    DBUG_EXECUTE_IF("ER_BACKUP_CATALOG_ADD_TRIGGER_2", db_found= NULL;);
+    if (!db_found)
+    {
+      // TODO: Consider more specific error message.
+      m_log.report_error(error, db.name().ptr(), obj->get_name()->ptr());
+      return NULL;
+    }
+    
+    trg_table= db_found->find_table(*tbl_obj->get_name());
+    
+    DBUG_EXECUTE_IF("ER_BACKUP_CATALOG_ADD_TRIGGER_3", trg_table= NULL;);
+    if (!trg_table)
+    {
+      // TODO: Consider more specific error message.
+      m_log.report_error(error, db.name().ptr(), obj->get_name()->ptr());
+      return NULL;
+    }
+  }
+
+  /*
     Add new object to the dependency list. If it is a view, add its
     dependencies first.
   */
@@ -1401,21 +1431,20 @@ Backup_info::add_db_object(Db &db, const
 
     Note: ER_BACKUP_CATALOG_ADD_TABLE is detected elsewhere.
   */
-  ::String str;
+  const char *err;
   switch (type) {
-  case BSTREAM_IT_DB:        str.append("ER_BACKUP_CATALOG_ADD_DB"); break;
-  case BSTREAM_IT_VIEW:      str.append("ER_BACKUP_CATALOG_ADD_VIEW"); break;
-  case BSTREAM_IT_SPROC:     str.append("ER_BACKUP_CATALOG_ADD_SROUT_P"); break;
-  case BSTREAM_IT_SFUNC:     str.append("ER_BACKUP_CATALOG_ADD_SROUT_F"); break;
-  case BSTREAM_IT_EVENT:     str.append("ER_BACKUP_CATALOG_ADD_EVENT"); break;
-  case BSTREAM_IT_TRIGGER:   str.append("ER_BACKUP_CATALOG_ADD_TRIGGER"); break;
-  case BSTREAM_IT_PRIVILEGE: str.append("ER_BACKUP_CATALOG_ADD_PRIV"); break;
+  case BSTREAM_IT_DB:        err= "ER_BACKUP_CATALOG_ADD_DB";      break;
+  case BSTREAM_IT_VIEW:      err= "ER_BACKUP_CATALOG_ADD_VIEW";    break;
+  case BSTREAM_IT_SPROC:     err= "ER_BACKUP_CATALOG_ADD_SROUT_P"; break;
+  case BSTREAM_IT_SFUNC:     err= "ER_BACKUP_CATALOG_ADD_SROUT_F"; break;
+  case BSTREAM_IT_EVENT:     err= "ER_BACKUP_CATALOG_ADD_EVENT";   break;
+  case BSTREAM_IT_TRIGGER:   err= "ER_BACKUP_CATALOG_ADD_TRIGGER"; break;
+  case BSTREAM_IT_PRIVILEGE: err= "ER_BACKUP_CATALOG_ADD_PRIV";    break;
   default: break;
   }
-  if (str.ptr())
-  {
-    DBUG_EXECUTE_IF(str.ptr(), res= get_dep_node_res::ERROR;);
-  }
+  if (err)
+    DBUG_EXECUTE_IF(err, res= get_dep_node_res::ERROR;);
+
   // Tablespace is a special case since Falcon is disabled.
   DBUG_EXECUTE_IF("ER_BACKUP_CATALOG_ADD_TS",
     m_log.report_error(ER_BACKUP_CATALOG_ADD_TS,
@@ -1458,7 +1487,7 @@ Backup_info::add_db_object(Db &db, const
     objects.
   */
 
-  Dbobj *o= Image_info::add_db_object(db, type, *obj->get_name(), pos);
+  Dbobj *o= Image_info::add_db_object(db, type, obj, pos);
 
   if (!o)
   {
@@ -1466,7 +1495,12 @@ Backup_info::add_db_object(Db &db, const
     return NULL;
   }
 
-  o->m_obj_ptr= obj;
+  // If we are inserting a trigger, save trigger's table coordinates.
+  if (trg_table)
+  {
+    o->snap_num= trg_table->snap_num;
+    o->pos=      trg_table->base.base.pos;
+  }
 
   /*
     Store a pointer to the catalogue item in the dep. list node. If this node

=== modified file 'sql/backup/image_info.cc'
--- a/sql/backup/image_info.cc	2009-11-04 14:18:21 +0000
+++ b/sql/backup/image_info.cc	2009-12-10 11:24:07 +0000
@@ -111,9 +111,9 @@ Image_info::~Image_info()
 */
 
 Image_info::Db*
-Image_info::add_db(const String &db_name, uint pos)
+Image_info::add_db(obs::Obj *db_obj, uint pos)
 {
-  Db *db= new (&mem_root) Db(db_name);
+  Db *db= new (&mem_root) Db(db_obj);
 
   if (!db)
     return NULL;
@@ -123,7 +123,18 @@ Image_info::add_db(const String &db_name
     m_dbs[pos]->~Db();
 
   if (m_dbs.insert(pos, db))
+  {
+    /*
+      We did not manage to successfully add db to the catalog. Thus we need 
+      to destroy it but first we set m_obj_ptr to NULL so that it is not 
+      deleted in the destructor. We assume ownership of the obs::Obj 
+      instance only if the object has been successfully added to the 
+      catalog.
+    */ 
+    db->m_obj_ptr= NULL;
+    db->~Db();
     return NULL;
+  }
 
   db->base.pos= pos;
 
@@ -144,9 +155,9 @@ Image_info::add_db(const String &db_name
 */
 
 Image_info::Ts*
-Image_info::add_ts(const String &ts_name, uint pos)
+Image_info::add_ts(obs::Obj *ts_obj, uint pos)
 {
-  Ts *ts= new (&mem_root) Ts(ts_name);
+  Ts *ts= new (&mem_root) Ts(ts_obj);
 
   if (!ts)
     return NULL;
@@ -156,7 +167,18 @@ Image_info::add_ts(const String &ts_name
     m_ts_map[pos]->~Ts();
 
   if (m_ts_map.insert(pos, ts))
+  {
+    /*
+      We did not manage to successfully add ts to the catalog. Thus we need 
+      to destroy it but first we set m_obj_ptr to NULL so that it is not 
+      deleted in the destructor. We assume ownership of the obs::Obj 
+      instance only if the object has been successfully added to the 
+      catalog.
+    */ 
+    ts->m_obj_ptr= NULL;
+    ts->~Ts();
     return NULL;
+  }
 
   ts->base.pos= pos;
 
@@ -215,15 +237,45 @@ int Image_info::add_snapshot(Snapshot_in
 }
 
 
-///  Check if catalogue contains given database.
+/**
+  Find in the catalog a database with the given name.
+
+  @param[in]    name of the database
+
+  @return Pointer to the catalog entry for the database if found, 
+  NULL otherwise.
 
-bool Image_info::has_db(const String &db_name) const
+  @todo More efficient implementation, e.g. using hash.
+*/
+
+Image_info::Db* Image_info::find_db(const String &db_name) const
 {
   for (uint n=0; n < m_dbs.count() ; ++n)
-    if (m_dbs[n] && m_dbs[n]->name() == db_name)
-      return TRUE;
+    if (m_dbs[n] && m_dbs[n]->m_obj_ptr->is_my_name(&db_name))
+      return m_dbs[n];
 
-  return FALSE;
+  return NULL;
+}
+
+
+/**
+  Find in the catalog a tablespace with the given name.
+
+  @param[in]    name of the tablespace
+
+  @return Pointer to the catalog entry for the tablespace if found, 
+  NULL otherwise.
+
+  @todo More efficient implementation, e.g. using hash.
+*/
+
+Image_info::Ts* Image_info::find_ts(const String &ts_name) const
+{
+  for (uint n=0; n < m_ts_map.count() ; ++n)
+    if (m_ts_map[n] && m_ts_map[n]->m_obj_ptr->is_my_name(&ts_name))
+      return m_ts_map[n];
+
+  return NULL;
 }
 
 
@@ -246,53 +298,31 @@ bool Image_info::has_db(const String &db
 */
 
 Image_info::Dbobj* Image_info::add_db_object(Db &db,
-                                             const enum_bstream_item_type type,
-                                             const ::String &name, ulong pos)
+                                             const obj_type type,
+                                             obs::Obj *obj_ptr, ulong pos)
 {
-  Dbobj *obj= new (&mem_root) Dbobj(db, type, name);
+  Dbobj *obj= new (&mem_root) Dbobj(db, type, obj_ptr);
 
   if (!obj)
     return NULL;
 
   if (db.add_obj(*obj, pos))
+  {
+    /*
+      We did not manage to successfully add obj to the catalog. Thus we need 
+      to destroy it but first we set m_obj_ptr to NULL so that it is not 
+      deleted in the destructor. We assume ownership of the obs::Obj 
+      instance only if the object has been successfully added to the 
+      catalog.
+    */ 
+    obj->m_obj_ptr= NULL;
+    obj->~Dbobj();
     return NULL;
+  }
 
   obj->base.pos= pos;
   count_object(type);
 
-  /*
-    If this is a trigger, get the table for the trigger.
-    Do this only for backup.
-  */
-  THD *thd= ::current_thd;
-  if ((type == BSTREAM_IT_TRIGGER) && 
-      (thd->backup_in_progress == SQLCOM_BACKUP))
-  {
-    obs::Obj *tbl_obj= obs::find_table_for_trigger(thd, &db.name(), &name);
-    DBUG_EXECUTE_IF("ER_BACKUP_CATALOG_ADD_TRIGGER_1", return NULL;);
-    if (!tbl_obj)
-      return NULL;
-    
-    Table *tbl_found;
-    Db *db_found= find_db(db.name());
-
-    DBUG_EXECUTE_IF("ER_BACKUP_CATALOG_ADD_TRIGGER_2", return NULL;);
-    if (!db_found)
-      return NULL;
-    
-    tbl_found= db_found->find_table(*tbl_obj->get_name());
-    
-    DBUG_EXECUTE_IF("ER_BACKUP_CATALOG_ADD_TRIGGER_3", return NULL;);
-    if (!tbl_found)
-      return NULL;
-    
-    /* 
-      Save table's snap and position values. 
-    */
-    obj->snap_num= tbl_found->snap_num;
-    obj->pos= tbl_found->base.base.pos;
-  }
-  
   return obj;
 }
 
@@ -338,25 +368,39 @@ Image_info::Dbobj* Image_info::get_db_ob
 */
 
 Image_info::Table*
-Image_info::add_table(Db &db, const ::String &table_name,
+Image_info::add_table(Db &db, obs::Obj *table_obj,
                       Snapshot_info &snap, ulong pos)
 {
-  Table *tbl= new (&mem_root) Table(db, table_name);
+  // Error code insertion for ER_BACKUP_CATALOG_ADD_TABLE.
+  DBUG_EXECUTE_IF("ER_BACKUP_CATALOG_ADD_TABLE", return NULL;);
+
+  if (!snap.m_num)
+    snap.m_num= add_snapshot(snap); // Reports errors.
+
+  if (!snap.m_num)
+   return NULL;
+
+  Table *tbl= new (&mem_root) Table(db, table_obj);
 
   if (!tbl)
     return NULL;
 
   if (snap.add_table(*tbl, pos))    // Reports errors.
+  {
+    /*
+      We did not manage to successfully add tbl to the catalog. Thus we need 
+      to destroy it but first we set m_obj_ptr to NULL so that it is not 
+      deleted in the destructor. We assume ownership of the obs::Obj 
+      instance only if the object has been successfully added to the 
+      catalog.
+    */ 
+    tbl->m_obj_ptr= NULL;
+    tbl->~Table();
     return NULL;
+  }
 
   db.add_table(*tbl);               // Never errors.
 
-  if (!snap.m_num)
-    snap.m_num= add_snapshot(snap); // Reports errors.
-
-  if (!snap.m_num)
-   return NULL;
-
   // Record the table count for the stream header.
   st_bstream_snapshot_info &info= snapshot[snap.m_num-1];
   info.table_count= snap.table_count();
@@ -394,27 +438,6 @@ Image_info::get_table(ushort snap_num, u
   return tbl;
 }
   
-/**
-  Return database stored in the catalogue.
- 
-  @param[in] db_name  The name of the database.
- 
-  @returns Pointer to @c Image_info::Db instance storing information
-  about the database or NULL if the database is not found.
-*/
-
-Image_info::Db*
-Image_info::find_db(const String &db_name)
-{
-  for (uint n=0; n < db_count(); ++n)
-  {
-    Image_info::Db *db= get_db(n);
-    
-    if (db && (db->name() == db_name))
-      return db;
-  }
-  return NULL;
-}
 
 /**
   Find object in the catalogue.

=== modified file 'sql/backup/image_info.h'
--- a/sql/backup/image_info.h	2009-11-04 14:18:21 +0000
+++ b/sql/backup/image_info.h	2009-12-10 11:24:07 +0000
@@ -105,7 +105,8 @@ public: // Public interface.
 
   // Examine contents of the catalogue.
 
-  bool has_db(const String&) const;
+  Db* find_db(const String&) const;
+  Ts* find_ts(const String&) const;
 
   // Retrieve objects using their coordinates.
 
@@ -113,7 +114,6 @@ public: // Public interface.
   Ts*    get_ts(uint pos) const;
   Dbobj* get_db_object(uint db_num, ulong pos) const;
   Table* get_table(ushort snap_num, ulong pos) const;
-  Db*    find_db(const String &db_name);
 
   // Iterators for enumerating the contents of the archive.
 
@@ -146,12 +146,10 @@ protected: // Internal interface.
   // Populate the catalogue.
 
   int    add_snapshot(Snapshot_info&);
-  Db*    add_db(const String &db_name, uint pos);
-  Ts*    add_ts(const String &db_name, uint pos);
-  Dbobj* add_db_object(Db &db, const obj_type type,
-                       const ::String &name, ulong pos);
-  Table* add_table(Db &db, const ::String &table_name,
-                   Snapshot_info &snap, ulong pos);
+  Db*    add_db(obs::Obj *db, uint pos);
+  Ts*    add_ts(obs::Obj *ts, uint pos);
+  Dbobj* add_db_object(Db &db, const obj_type type, obs::Obj *obj, ulong pos);
+  Table* add_table(Db &db, obs::Obj *tbl, Snapshot_info &snap, ulong pos);
 
   // IMPLEMENTATION
 
@@ -383,9 +381,6 @@ public:
   /// Pointer to the corresponding @c obs::Obj instance, if it is known.
   obs::Obj  *m_obj_ptr;
 
-  /// Create corresponding @c obs::Obj instance from a serialization string.
-  virtual obs::Obj *materialize(uint ver, const ::String&) =0;
-
   /// Definition for a table name in a Table_ref object.
   typedef Table_ref::name_buf describe_buf;
 
@@ -394,18 +389,15 @@ public:
 
 protected:
 
-  String m_name;  ///< For storing object's name.
-
-  void store_name(const String&);
-
-  Obj();
+  Obj(obs::Obj *obj_ptr);
+  void store_info(const obj_type type);
 
   friend class Image_info;
 };
 
 
 inline
-Image_info::Obj::Obj() :m_obj_ptr(NULL)
+Image_info::Obj::Obj(obs::Obj *obj_ptr) :m_obj_ptr(obj_ptr)
 {}
 
 
@@ -421,12 +413,13 @@ Image_info::Obj::~Obj()
 
 class Image_info::Ts
  : public st_bstream_ts_info,
-   public Image_info::Obj
+   public Image_info::Obj,
+   public Db_ref
 {
 public:
 
   /// Constructor.
-  Ts(const ::String&);
+  Ts(obs::Obj *obj_ptr);
 
   /// The information about the image.
   const st_bstream_item_info* info() const;
@@ -439,11 +432,10 @@ public:
 
 
 inline
-Image_info::Ts::Ts(const ::String &name)
+Image_info::Ts::Ts(obs::Obj *obj_ptr)
+  : Obj(obj_ptr), Db_ref(*obj_ptr->get_name())
 {
-  bzero(&base, sizeof(base));
-  base.type= BSTREAM_IT_TABLESPACE;
-  store_name(name);
+  store_info(BSTREAM_IT_TABLESPACE);
 }
 
 
@@ -459,7 +451,7 @@ class Image_info::Db
 public:
 
   /// Constuctor.
-  Db(const ::String&);
+  Db(obs::Obj *obj_ptr);
 
   const st_bstream_item_info* info() const;
   /// The database information in the stream.
@@ -472,7 +464,8 @@ public:
   /// Description of object.
   const char* describe(describe_buf&) const;
   /// Search for table in database table list.
-  Table* find_table(const String &table_name);
+  Table* find_table(const String &table_name) const;
+  Dbobj* find_object(const obj_type type, const String &name) const;
 
 private:
 
@@ -491,13 +484,11 @@ private:
 
 
 inline
-Image_info::Db::Db(const ::String &name)
- :Db_ref(Image_info::Obj::m_name),
-  m_obj_count(0), first_table(NULL), last_table(NULL), m_objs(128)
-{
-  bzero(&base, sizeof(base));
-  base.type= BSTREAM_IT_DB;
-  store_name(name);
+Image_info::Db::Db(obs::Obj *obj_ptr)
+ : Obj(obj_ptr), Db_ref(*obj_ptr->get_name()),
+   m_obj_count(0), first_table(NULL), last_table(NULL), m_objs(128)
+{
+  store_info(BSTREAM_IT_DB);
 }
 
 
@@ -518,7 +509,7 @@ class Image_info::Dbobj
 public:
 
   /// Constructor.
-  Dbobj(const Db &db, const obj_type type, const ::String &name);
+  Dbobj(const Db &db, const obj_type type, obs::Obj *obj_ptr);
 
   const st_bstream_item_info* info() const;
   obs::Obj* materialize(uint ver, const ::String &sdata);
@@ -531,14 +522,11 @@ public:
 
 
 inline
-Image_info::Dbobj::Dbobj(const Db &db, const obj_type type,
-                         const ::String &name)
-  :Table_ref(db.name(), Image_info::Obj::m_name), m_db(db)
+Image_info::Dbobj::Dbobj(const Db &db, const obj_type type, obs::Obj *obj_ptr)
+  : Obj(obj_ptr), Table_ref(db.name(), *obj_ptr->get_name()), m_db(db)
 {
-  bzero(&base, sizeof(base));
-  base.type= type;
+  store_info(type);
   st_bstream_dbitem_info::db= const_cast<st_bstream_db_info*>(m_db.db_info());
-  store_name(name);
 }
 
 
@@ -556,7 +544,7 @@ class Image_info::Table
 public:
 
   /// Constructor.
-  Table(const Db &db, const ::String &name);
+  Table(const Db &db, obs::Obj *obj_ptr);
 
   const st_bstream_item_info* info() const;
   obs::Obj* materialize(uint ver, const ::String &sdata);
@@ -571,15 +559,13 @@ public:
 
 
 inline
-Image_info::Table::Table(const Db &db, const ::String &name)
-  :Table_ref(db.name(), Image_info::Obj::m_name), m_db(db), next_table(NULL),
-   m_table(NULL)
-{
-  bzero(&base, sizeof(base));
-  base.base.type= BSTREAM_IT_TABLE;
-  base.db= const_cast<st_bstream_db_info*>(db.db_info());
+Image_info::Table::Table(const Db &db, obs::Obj *obj_ptr)
+  : Obj(obj_ptr), Table_ref(db.name(), *obj_ptr->get_name()), 
+    m_db(db), next_table(NULL), m_table(NULL)
+{
+  store_info(BSTREAM_IT_TABLE);
+  base.db= const_cast<st_bstream_db_info*>(m_db.db_info());
   snap_num= 0;
-  store_name(name);
 }
 
 
@@ -1091,12 +1077,15 @@ Table_ref Image_info::Tables::operator[]
  */
 
 inline
-void Image_info::Obj::store_name(const String &name)
+void Image_info::Obj::store_info(const obj_type type)
 {
-  m_name.copy(name);
+  const ::String *name= m_obj_ptr->get_name();
   st_bstream_item_info *info= const_cast<st_bstream_item_info*>(this->info());
-  info->name.begin= (byte*)name.ptr();
-  info->name.end= info->name.begin + name.length();
+  bzero(info, sizeof(st_bstream_item_info));
+  info->type= type;
+  DBUG_ASSERT(name);
+  info->name.begin= (byte*)name->ptr();
+  info->name.end= info->name.begin + name->length();
 }
 
 
@@ -1168,8 +1157,7 @@ const st_bstream_item_info* Image_info::
 inline
 const char* Image_info::Ts::describe(describe_buf &buf) const
 {
-  my_snprintf(buf, sizeof(buf), "`%s`", Obj::m_name.ptr());
-  return buf;
+  return Db_ref::describe(buf);
 }
 
 
@@ -1178,10 +1166,10 @@ const char* Image_info::Ts::describe(des
 inline
 const char* Image_info::Db::describe(describe_buf &buf) const
 {
-  my_snprintf(buf, sizeof(buf), "`%s`", Obj::m_name.ptr());
-  return buf;
+  return Db_ref::describe(buf);
 }
 
+
 /**
   Search for a table in the database catalog by name.
  
@@ -1189,104 +1177,64 @@ const char* Image_info::Db::describe(des
  
   @returns Pointer to @c Image_info::Table instance storing information
   about the table or NULL if the table is not found.
+
+  @todo More efficient implementation, e.g. using hash.
 */
 inline
-Image_info::Table* Image_info::Db::find_table(const String &table_name)
+Image_info::Table* 
+Image_info::Db::find_table(const String &name) const
 {
   for (Table *tbl=first_table; tbl ; tbl= tbl->next_table)
   {
-    if (tbl->name() == table_name)
+    DBUG_ASSERT(tbl->m_obj_ptr);
+    if (tbl->m_obj_ptr->is_my_name(&name))
       return tbl;
   }
   return NULL;
 }
 
-/// Implementation of @c Image_info::Obj virtual method.
 
-inline
-const char* Image_info::Table::describe(Obj::describe_buf &buf) const
-{
-  return Table_ref::describe(buf);
-}
-
-
-/// Implementation of @c Image_info::Obj virtual method.
-
-inline
-const char* Image_info::Dbobj::describe(Obj::describe_buf &buf) const
-{
-  return Table_ref::describe(buf);
-}
-
-
-/// Implementation of @c Image_info::Obj virtual method.
+/**
+  Search for an object of a given type by its name.
+ 
+  @param[in] obj_type    Type of the object.
+  @param[in] table_name  The name of the object.
+ 
+  @returns Pointer to @c Image_info::Dbobj instance storing information
+  about the object or NULL if the object is not found.
 
+  @todo More efficient implementation, e.g. using hash.
+*/
 inline
-obs::Obj* Image_info::Ts::materialize(uint ver, const ::String &sdata)
+Image_info::Dbobj* 
+Image_info::Db::find_object(const obj_type type, const String &name) const
 {
-  delete m_obj_ptr;
-  return m_obj_ptr= obs::get_tablespace(&m_name, ver, &sdata);
+  for (uint pos=0; pos < obj_count(); ++pos)
+  {
+    Dbobj *obj= get_obj(pos);
+    DBUG_ASSERT(!obj || obj->m_obj_ptr);
+    if (obj && obj->type() == type && obj->m_obj_ptr->is_my_name(&name))
+      return obj;
+  }
+  return NULL;
 }
 
 
 /// Implementation of @c Image_info::Obj virtual method.
 
 inline
-obs::Obj* Image_info::Db::materialize(uint ver, const ::String &sdata)
+const char* Image_info::Table::describe(Obj::describe_buf &buf) const
 {
-  delete m_obj_ptr;
-  return m_obj_ptr= obs::get_database(&name(), ver, &sdata);
+  return Table_ref::describe(buf);
 }
 
 
 /// Implementation of @c Image_info::Obj virtual method.
 
 inline
-obs::Obj* Image_info::Table::materialize(uint ver, const ::String &sdata)
-{
-  delete m_obj_ptr;
-  return m_obj_ptr= obs::get_table(&db().name(), &name(), ver, &sdata);
-}
-
-
-inline
-obs::Obj* Image_info::Dbobj::materialize(uint ver, const ::String &sdata)
+const char* Image_info::Dbobj::describe(Obj::describe_buf &buf) const
 {
-  const ::String *db_name= &Table_ref::db().name();
-  const ::String *name= &Table_ref::name();
-
-  delete m_obj_ptr;
-
-  switch (base.type) {
-
-  case BSTREAM_IT_VIEW:
-    m_obj_ptr= obs::get_view(db_name, name, ver, &sdata);
-    break;
-
-  case BSTREAM_IT_SPROC:
-    m_obj_ptr= obs::get_stored_procedure(db_name, name, ver, &sdata);
-    break;
-
-  case BSTREAM_IT_SFUNC:
-    m_obj_ptr= obs::get_stored_function(db_name, name, ver, &sdata);
-    break;
-
-  case BSTREAM_IT_EVENT:
-    m_obj_ptr= obs::get_event(db_name, name, ver, &sdata);
-    break;
-
-  case BSTREAM_IT_TRIGGER:
-    m_obj_ptr= obs::get_trigger(db_name, name, ver, &sdata);
-    break;
-
-  case BSTREAM_IT_PRIVILEGE:
-    m_obj_ptr= obs::get_db_grant(db_name, name, ver, &sdata);
-    break;
-
-  default: m_obj_ptr= NULL;
-  }
-
-  return m_obj_ptr;
+  return Table_ref::describe(buf);
 }
 
 

=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc	2009-12-02 08:01:43 +0000
+++ b/sql/backup/kernel.cc	2009-12-10 11:24:07 +0000
@@ -1482,7 +1482,6 @@ int Backup_restore_ctx::restore_triggers
       switch (obj->type()) {
 
       case BSTREAM_IT_EVENT:
-        DBUG_ASSERT(obj->m_obj_ptr);
         if (events.push_back(obj))
         {
           /* Error has been reported, but not logged to backup logs. */
@@ -1493,7 +1492,6 @@ int Backup_restore_ctx::restore_triggers
 
       case BSTREAM_IT_TRIGGER:
       {
-        DBUG_ASSERT(obj->m_obj_ptr);
         int ret= obj->m_obj_ptr->create(m_thd);
         /* Mimic error in restore of trigger. */
         DBUG_EXECUTE_IF("restore_trigger", ret= TRUE;);
@@ -2056,17 +2054,30 @@ int bcat_add_item(st_bstream_image_heade
 
   case BSTREAM_IT_TABLESPACE:
   {
-    Image_info::Ts *ts= info->add_ts(name_str, item->pos); // Reports errors.
+    obs::Obj *ts_obj= obs::get_tablespace(&name_str);
+
+    if (!ts_obj)
+    {
+      log.report_error(ER_BACKUP_CATALOG_ADD_TS, name_str.ptr());
+      return BSTREAM_ERROR;
+    }
+
+    Image_info::Ts *ts= info->add_ts(ts_obj, item->pos); // Reports errors.
 
     return ts ? BSTREAM_OK : BSTREAM_ERROR;
   }
 
   case BSTREAM_IT_DB:
   {
+    obs::Obj *db_obj= obs::get_database(&name_str);
 
-    if (lower_case_table_names == 1)
-      my_casedn_str(system_charset_info, name_str.c_ptr());
-    Image_info::Db *db= info->add_db(name_str, item->pos); // Reports errors.
+    if (!db_obj)
+    {
+      log.report_error(ER_BACKUP_CATALOG_ADD_DB, name_str.ptr());
+      return BSTREAM_ERROR;
+    }
+
+    Image_info::Db *db= info->add_db(db_obj, item->pos); // Reports errors.
 
     return db ? BSTREAM_OK : BSTREAM_ERROR;
   }
@@ -2101,9 +2112,16 @@ int bcat_add_item(st_bstream_image_heade
 
     DBUG_PRINT("restore",(" table's database is %s", db->name().ptr()));
 
-    if (lower_case_table_names == 1)
-      my_casedn_str(system_charset_info, name_str.c_ptr());
-    Image_info::Table *tbl= info->add_table(*db, name_str, *snap, item->pos);
+    obs::Obj *tbl_obj= obs::get_table(&db->name(), &name_str);
+
+    if (!tbl_obj)
+    {
+      log.report_error(ER_BACKUP_CATALOG_ADD_TABLE, db->name().ptr(), 
+                                                    name_str.ptr());
+      return BSTREAM_ERROR;
+    }
+
+    Image_info::Table *tbl= info->add_table(*db, tbl_obj, *snap, item->pos);
                                                              // Reports errors.
 
     return tbl ? BSTREAM_OK : BSTREAM_ERROR;
@@ -2122,10 +2140,50 @@ int bcat_add_item(st_bstream_image_heade
 
     Image_info::Db *db= (Image_info::Db*) info->get_db(it->db->base.pos);
 
-    DBUG_ASSERT(db);
+    if (!db)
+      return BSTREAM_ERROR;
+
+    obs::Obj *obj;
+    int      error;
 
-    Image_info::Dbobj *it1= info->add_db_object(*db, item->type, name_str,
-                                                item->pos);
+    switch (item->type)
+    {
+      case BSTREAM_IT_VIEW:
+         error= ER_BACKUP_CATALOG_ADD_VIEW;
+         obj= obs::get_view(&db->name(), &name_str); 
+         break;
+      case BSTREAM_IT_SPROC:
+         error= ER_BACKUP_CATALOG_ADD_SROUT;
+         obj= obs::get_stored_procedure(&db->name(), &name_str);
+         break;
+      case BSTREAM_IT_SFUNC:
+         error= ER_BACKUP_CATALOG_ADD_SROUT;
+        obj= obs::get_stored_function(&db->name(), &name_str);
+        break;
+      case BSTREAM_IT_EVENT:
+        error= ER_BACKUP_CATALOG_ADD_EVENT;
+        obj= obs::get_event(&db->name(), &name_str);
+        break;
+      case BSTREAM_IT_TRIGGER:
+        error= ER_BACKUP_CATALOG_ADD_TRIGGER;
+        obj= obs::get_trigger(&db->name(), &name_str);
+        break;
+      case BSTREAM_IT_PRIVILEGE:
+        error= ER_BACKUP_CATALOG_ADD_PRIV;
+        obj= obs::get_db_grant(&db->name(), &name_str);
+        break;
+      default: DBUG_ASSERT(FALSE);    
+    }
+
+    if (!obj)
+    {
+      log.report_error(error, db->name().ptr(), name_str.ptr());
+      return BSTREAM_ERROR;
+    }
+
+    // Reports errors.
+    Image_info::Dbobj *it1= 
+                          info->add_db_object(*db, item->type, obj, item->pos);
     if (!it1)
       return BSTREAM_ERROR;
 
@@ -2374,6 +2432,7 @@ int bcat_create_item(st_bstream_image_he
   Logger       &log=  info->m_log;
   THD          *thd=  info->m_thd;
   int          create_err= 0;
+  int          ret= 0;
 
   /*
     Check for interruption before creating (and thus first destroying)
@@ -2417,19 +2476,16 @@ int bcat_create_item(st_bstream_image_he
     return BSTREAM_ERROR;
   }
 
-  backup::String sdata(create_stmt.begin, create_stmt.end);
-
-  DBUG_PRINT("restore",("Creating item of type %d pos %ld: %s",
-                         item->type, item->pos, sdata.ptr()));
-  /*
-    Note: The instance created by Image_info::Obj::materialize() is deleted
-    when *info is destroyed.
-  */
-  obs::Obj *sobj= obj->materialize(0, sdata);
+  DBUG_ASSERT(obj->m_obj_ptr);
 
+  const ::String *name= obj->m_obj_ptr->get_name(); 
   Image_info::Obj::describe_buf buf;
   const char *desc= obj->describe(buf);
 
+  backup::String sdata(create_stmt.begin, create_stmt.end);
+
+  ret= obj->m_obj_ptr->init_from_image(0, &sdata);
+
 #if !defined(DBUG_OFF)
 
   /*
@@ -2439,42 +2495,30 @@ int bcat_create_item(st_bstream_image_he
     Note: Error code insertion won't work here as we need to generate
           the specific error message for each test case.
   */
-  ::String str;
+  const char *err= NULL;
   switch (item->type) {
-  case BSTREAM_IT_DB:      str.append("ER_BACKUP_CANT_RESTORE_DB"); break;
-  case BSTREAM_IT_TABLE:   str.append("ER_BACKUP_CANT_RESTORE_TABLE"); break;
-  case BSTREAM_IT_VIEW:    str.append("ER_BACKUP_CANT_RESTORE_VIEW"); break;
-  case BSTREAM_IT_SPROC:   str.append("ER_BACKUP_CANT_RESTORE_SROUT_P"); break;
-  case BSTREAM_IT_SFUNC:   str.append("ER_BACKUP_CANT_RESTORE_SROUT_F"); break;
-  case BSTREAM_IT_EVENT:   str.append("ER_BACKUP_CANT_RESTORE_EVENT_2"); break;
-  case BSTREAM_IT_TRIGGER: str.append("ER_BACKUP_CANT_RESTORE_TRIGGER"); break;
+  case BSTREAM_IT_DB:      err= "ER_BACKUP_CANT_RESTORE_DB";      break;
+  case BSTREAM_IT_TABLE:   err= "ER_BACKUP_CANT_RESTORE_TABLE";   break;
+  case BSTREAM_IT_VIEW:    err= "ER_BACKUP_CANT_RESTORE_VIEW";    break;
+  case BSTREAM_IT_SPROC:   err= "ER_BACKUP_CANT_RESTORE_SROUT_P"; break;
+  case BSTREAM_IT_SFUNC:   err= "ER_BACKUP_CANT_RESTORE_SROUT_F"; break;
+  case BSTREAM_IT_EVENT:   err= "ER_BACKUP_CANT_RESTORE_EVENT_2"; break;
+  case BSTREAM_IT_TRIGGER: err= "ER_BACKUP_CANT_RESTORE_TRIGGER"; break;
+  case BSTREAM_IT_PRIVILEGE:  err= "ER_BACKUP_CANT_RESTORE_PRIV"; break;
   default: break;
   }
-  if (str.ptr())
-  {
-    DBUG_EXECUTE_IF(str.ptr(),
-      log.report_error(create_err, desc);
-      return BSTREAM_ERROR;);
-  }
+  if (err)
+    DBUG_EXECUTE_IF(err, ret= ERROR;);
+
   /* Tablespace is a special case since Falcon is disabled. */
   DBUG_EXECUTE_IF("ER_BACKUP_CANT_RESTORE_TS",
     log.report_error(ER_BACKUP_CANT_RESTORE_TS,
       "Debug insertion test");
     return BSTREAM_ERROR;);
 
-  /*
-     Grants are a special case because of the way the message is generated --
-     it produces a non-deterministic error string. Note that a real error
-     would be deterministic.
-  */
-  DBUG_EXECUTE_IF("ER_BACKUP_CANT_RESTORE_PRIV",
-    log.report_error(ER_BACKUP_CANT_RESTORE_PRIV,
-      "Debug insertion test");
-    return BSTREAM_ERROR;);
-
 #endif
 
-  if (!sobj)
+  if (ret)
   {
     log.report_error(create_err, desc);
     return BSTREAM_ERROR;
@@ -2496,11 +2540,14 @@ int bcat_create_item(st_bstream_image_he
 
   }
 
+  DBUG_PRINT("restore",("Creating item %s of type %d pos %ld: %s",
+                         desc, item->type, item->pos, sdata.ptr()));
+
   /* If we are to create a tablespace, first check if it already exists. */
 
   if (item->type == BSTREAM_IT_TABLESPACE)
   {
-    if (obs::find_tablespace(thd, sobj->get_name()))
+    if (obs::find_tablespace(thd, name))
     {
       // A tablespace with the same name exists. Nothing more to do.
       DBUG_PRINT("restore",(" skipping tablespace which exists"));
@@ -2523,19 +2570,22 @@ int bcat_create_item(st_bstream_image_he
             error handling work in WL#4384 with possible implementation
             via a related bug report.
     */
-    if (!obs::check_user_existence(thd, sobj))
+    if (!obs::check_user_existence(thd, obj->m_obj_ptr))
     {
-      log.report_error(log_level::WARNING,
-                       ER_BACKUP_GRANT_SKIPPED,
-                       obs::grant_get_grant_info(sobj)->ptr(),
-                       obs::grant_get_user_name(sobj)->ptr());
+      const ::String *info= obs::grant_get_grant_info(obj->m_obj_ptr);
+      const ::String *user= obs::grant_get_user_name(obj->m_obj_ptr);
+
+      log.report_error(log_level::WARNING, ER_BACKUP_GRANT_SKIPPED, 
+                       info->ptr(), user->ptr());
+
       return BSTREAM_OK;
     }
   }
 
   /* Mark that data is being changed. */
   info->m_data_changed= TRUE;
-  if (sobj->create(thd))
+  ret= obj->m_obj_ptr->create(thd);
+  if (ret)
   {
     log.report_error(create_err, desc);
     return BSTREAM_ERROR;
@@ -2571,6 +2621,7 @@ int bcat_get_item_create_query(st_bstrea
   Backup_info *info= static_cast<Backup_info*>(catalogue);
   Logger &log= info->m_log;
   int meta_err= 0;
+  int ret= 0;
 
   /* Check for interruption before proceeding. */
   if (log.report_killed())
@@ -2612,6 +2663,8 @@ int bcat_get_item_create_query(st_bstrea
   ::String *buf= &(info->serialization_buf);
   buf->length(0);
 
+  ret= obj->m_obj_ptr->serialize(info->m_thd, buf);
+
 #if !defined(DBUG_OFF)
 
   /*
@@ -2621,43 +2674,30 @@ int bcat_get_item_create_query(st_bstrea
     Note: Error code insertion won't work here as we need to generate
           the specific error message for each test case.
   */
-  ::String str;
+  const char *err= NULL;
   switch (item->type) {
-  case BSTREAM_IT_DB:      str.append("ER_BACKUP_GET_META_DB"); break;
-  case BSTREAM_IT_TABLE:   str.append("ER_BACKUP_GET_META_TABLE"); break;
-  case BSTREAM_IT_VIEW:    str.append("ER_BACKUP_GET_META_VIEW"); break;
-  case BSTREAM_IT_SPROC:   str.append("ER_BACKUP_GET_META_SROUT_P"); break;
-  case BSTREAM_IT_SFUNC:   str.append("ER_BACKUP_GET_META_SROUT_F"); break;
-  case BSTREAM_IT_EVENT:   str.append("ER_BACKUP_GET_META_EVENT"); break;
-  case BSTREAM_IT_TRIGGER: str.append("ER_BACKUP_GET_META_TRIGGER"); break;
+  case BSTREAM_IT_DB:      err= "ER_BACKUP_GET_META_DB";      break;
+  case BSTREAM_IT_TABLE:   err= "ER_BACKUP_GET_META_TABLE";   break;
+  case BSTREAM_IT_VIEW:    err= "ER_BACKUP_GET_META_VIEW";    break;
+  case BSTREAM_IT_SPROC:   err= "ER_BACKUP_GET_META_SROUT_P"; break;
+  case BSTREAM_IT_SFUNC:   err= "ER_BACKUP_GET_META_SROUT_F"; break;
+  case BSTREAM_IT_EVENT:   err= "ER_BACKUP_GET_META_EVENT";   break;
+  case BSTREAM_IT_TRIGGER: err= "ER_BACKUP_GET_META_TRIGGER"; break;
+  case BSTREAM_IT_PRIVILEGE:  err= "ER_BACKUP_GET_META_PRIV"; break;
   default: break;
   }
-  if (str.ptr())
-  {
-    DBUG_EXECUTE_IF(str.ptr(),
-      Image_info::Obj::describe_buf dbuf;
-      log.report_error(meta_err, obj->describe(dbuf));
-      return BSTREAM_ERROR;);
-  }
+  if (err)
+    DBUG_EXECUTE_IF(err, ret= ERROR;);
+
   /* Tablespace is a special case since Falcon is disabled. */
   DBUG_EXECUTE_IF("ER_BACKUP_GET_META_TS",
     log.report_error(ER_BACKUP_GET_META_TS,
       "Debug insertion test");
     return BSTREAM_ERROR;);
 
-  /*
-     Grants are a special case because of the way the message is generated --
-     it produces a non-deterministic error string. Note that a real error
-     would be deterministic.
-  */
-  DBUG_EXECUTE_IF("ER_BACKUP_GET_META_PRIV",
-    log.report_error(ER_BACKUP_GET_META_PRIV,
-      "Debug insertion test");
-    return BSTREAM_ERROR;);
-
 #endif
 
-  if (obj->m_obj_ptr->serialize(info->m_thd, buf))
+  if (ret)
   {
     Image_info::Obj::describe_buf dbuf;
 
@@ -2700,6 +2740,11 @@ namespace backup {
 /**
   Produce string identifying the table in internal format (as used by
   storage engines).
+
+  @param[in]   buf      buffer where the name will be created
+  @param[in]   len      size of the buffer
+
+  @return Pointer to the buffer containing string with table name.
 */
 
 const char* Table_ref::internal_name(char *buf, size_t len) const
@@ -2714,8 +2759,29 @@ const char* Table_ref::internal_name(cha
 
 
 /**
+  Produce human readable string identifying the database
+  (e.g. for error reporting).
+
+  @param[in]   buf      buffer where the name will be created
+  @param[in]   len      size of the buffer
+
+  @return Pointer to the buffer containing string with database name.
+*/
+
+const char* Db_ref::describe(char *buf, size_t len) const
+{
+  my_snprintf(buf, len, "`%s`", name().ptr());
+  return buf;
+}
+
+/**
   Produce human readable string identifying the table
   (e.g. for error reporting).
+
+  @param[in]   buf      buffer where the name will be created
+  @param[in]   len      size of the buffer
+
+  @return Pointer to the buffer containing string with table name.
 */
 
 const char* Table_ref::describe(char *buf, size_t len) const

=== modified file 'sql/backup/restore_info.h'
--- a/sql/backup/restore_info.h	2009-12-01 01:49:23 +0000
+++ b/sql/backup/restore_info.h	2009-12-10 11:24:07 +0000
@@ -41,10 +41,12 @@ public:
   /// Determine of information class is valid.
   bool is_valid();
 
-  Image_info::Ts* add_ts(const ::String&, uint);
-  Image_info::Db* add_db(const ::String&, uint);
-  Image_info::Table* add_table(Image_info::Db&, const ::String&,
+  Image_info::Ts*    add_ts(obs::Obj*, uint);
+  Image_info::Db*    add_db(obs::Obj*, uint);
+  Image_info::Table* add_table(Image_info::Db&, obs::Obj*,
                                backup::Snapshot_info&, ulong);
+  Image_info::Dbobj* add_db_object(Image_info::Db &db, const obj_type type, 
+                                   obs::Obj*, ulong pos);
                                
   bool check_restore_privileges(struct st_bstream_item_info *item);
   
@@ -115,12 +117,20 @@ bool Restore_info::is_valid()
 
 inline
 backup::Image_info::Ts*
-Restore_info::add_ts(const ::String &name, uint pos)
+Restore_info::add_ts(obs::Obj *ts_obj, uint pos)
 {
-  Ts *ts= Image_info::add_ts(name, pos);
+  const String *name= ts_obj->get_name();
+
+  if (Ts *other= find_ts(*name))
+  {
+    m_log.report_error(ER_RESTORE_NONUNIQUE_OBJECT, other->name().ptr());
+    return NULL;
+  }
+
+  Ts *ts= Image_info::add_ts(ts_obj, pos);
 
   if (!ts)
-    m_log.report_error(ER_BACKUP_CATALOG_ADD_TS, name.ptr());
+    m_log.report_error(ER_BACKUP_CATALOG_ADD_TS, name->ptr());
 
   return ts;
 }
@@ -130,12 +140,20 @@ Restore_info::add_ts(const ::String &nam
 
 inline
 backup::Image_info::Db*
-Restore_info::add_db(const ::String &name, uint pos)
+Restore_info::add_db(obs::Obj *db_obj, uint pos)
 {
-  Db *db= Image_info::add_db(name, pos);
+  const String *name= db_obj->get_name();
+
+  if (Db *other= find_db(*name))
+  {
+    m_log.report_error(ER_RESTORE_NONUNIQUE_OBJECT, other->name().ptr());
+    return NULL;
+  }
+
+  Db *db= Image_info::add_db(db_obj, pos);
 
   if (!db)
-    m_log.report_error(ER_BACKUP_CATALOG_ADD_DB, name.ptr());
+    m_log.report_error(ER_BACKUP_CATALOG_ADD_DB, name->ptr());
 
   return db;
 }
@@ -145,16 +163,43 @@ Restore_info::add_db(const ::String &nam
 
 inline
 backup::Image_info::Table*
-Restore_info::add_table(Image_info::Db &db, const ::String &name,
+Restore_info::add_table(Image_info::Db &db, obs::Obj *table_obj,
                         backup::Snapshot_info &snap, ulong pos)
 {
-  Table *t= Image_info::add_table(db, name, snap, pos);
+  const String *name= table_obj->get_name();
+
+  if (Table *other= db.find_table(*name))
+  {
+    m_log.report_error(ER_RESTORE_NONUNIQUE_DBOBJECT, other->name().ptr(), 
+                                                      db.name().ptr());
+    return NULL;
+  }
+
+  Table *t= Image_info::add_table(db, table_obj, snap, pos);
 
   if (!t)
     m_log.report_error(ER_BACKUP_CATALOG_ADD_TABLE, db.name().ptr(), 
-                       name.ptr());
+                       name->ptr());
 
   return t;
 }
 
+
+inline
+backup::Image_info::Dbobj*
+Restore_info::add_db_object(Image_info::Db &db, const obj_type type, 
+                            obs::Obj *obj, ulong pos)
+{
+  if (Dbobj *other= db.find_object(type, *obj->get_name()))
+  {
+    m_log.report_error(ER_RESTORE_NONUNIQUE_DBOBJECT, other->name().ptr(), 
+                                                      db.name().ptr());
+    return NULL;
+  }
+
+  Dbobj *ob= Image_info::add_db_object(db, type, obj, pos);
+
+  return ob;
+}
+
 #endif /*RESTORE_INFO_H_*/

=== modified file 'sql/share/errmsg-utf8.txt'
--- a/sql/share/errmsg-utf8.txt	2009-12-01 01:49:23 +0000
+++ b/sql/share/errmsg-utf8.txt	2009-12-10 11:24:07 +0000
@@ -6572,4 +6572,7 @@ ER_RESTORE_ACCESS_DEFINER
   eng "Insufficient privileges. You must have the SUPER privilege to restore the object '%s'.'%s'."
 ER_RESTORE_DB_ERROR
   eng "The database for object '%s' was not found in the catalog."
-
+ER_RESTORE_NONUNIQUE_OBJECT
+  eng "Backup image contains two objects named '%.64s'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1."
+ER_RESTORE_NONUNIQUE_DBOBJECT
+  eng "Backup image contains two objects named '%.64s' in database '%.64s'. The problem might be that objects' names differ in letter case only and you are restoring on a case insensitive system or --lower-case-table is set to 1."

=== modified file 'sql/si_objects.cc'
--- a/sql/si_objects.cc	2009-12-01 01:49:23 +0000
+++ b/sql/si_objects.cc	2009-12-10 11:24:07 +0000
@@ -577,13 +577,10 @@ namespace obs {
 class Abstract_obj : public Obj
 {
 public:
-  static Obj *init_obj_from_image(Abstract_obj *obj,
-                                  uint image_version,
-                                  const String *image);
-
-public:
   virtual inline const String *get_name() const    { return &m_id; }
   virtual inline const String *get_db_name() const { return NULL; }
+  virtual inline bool is_my_name(const String *name) const 
+  { return *name == m_id; }
 
 public:
   /**
@@ -653,7 +650,8 @@ protected:
   String m_id; //< identify object
 
 protected:
-  inline Abstract_obj(LEX_STRING id);
+  inline Abstract_obj(LEX_STRING id, bool lc_name= FALSE);
+  inline bool is_my_name_lctn(const String *name) const; 
 
   virtual inline ~Abstract_obj();
 
@@ -664,30 +662,22 @@ private:
 
 ///////////////////////////////////////////////////////////////////////////
 
-Obj *Abstract_obj::init_obj_from_image(Abstract_obj *obj,
-                                       uint image_version,
-                                       const String *image)
-{
-  if (!obj)
-    return NULL;
-
-  if (obj->init_from_image(image_version, image))
-  {
-    delete obj;
-    return NULL;
-  }
-
-  return obj;
-}
-
-///////////////////////////////////////////////////////////////////////////
+/**
+  Create instance of an object with given name.
 
-inline Abstract_obj::Abstract_obj(LEX_STRING id)
+  @param[in]  id       Name of the object.
+  @param[in]  lc_name  Should id be converted to lower case.
+*/ 
+inline Abstract_obj::Abstract_obj(LEX_STRING id, bool lc_name)
 {
   init_sql_alloc(&m_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
 
   if (id.str && id.length)
+  {
     m_id.copy(id.str, id.length, system_charset_info);
+    if (lc_name)
+      my_casedn_str(system_charset_info, m_id.c_ptr());      
+  }
   else
     m_id.length(0);
   m_errno= 0;
@@ -873,6 +863,21 @@ bool Abstract_obj::do_init_from_image(In
 }
 
 ///////////////////////////////////////////////////////////////////////////
+
+/** 
+  Alternative implementation of @c is_my_name() which takes into account the
+  --lower-case-table-names setting. If option is set, it considers all names
+  which differ from id in case only as referring to this object.
+*/
+bool Abstract_obj::is_my_name_lctn(const String *name) const
+{
+  if (lower_case_table_names)
+    return 0 == my_strcasecmp(system_charset_info, name->ptr(), m_id.ptr());
+  else
+    return m_id == *name;
+}
+
+///////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////
 
 /**
@@ -890,13 +895,15 @@ public:
   { }
 
   inline Database_obj(LEX_STRING db_name)
-    : Abstract_obj(db_name)
+    : Abstract_obj(db_name, lower_case_table_names == 1)
   { }
 
 public:
   virtual inline const String *get_db_name() const { return get_name(); }
   virtual bool drop(THD *thd);
-
+  virtual inline bool is_my_name(const String *name) const 
+  { return is_my_name_lctn(name); }
+  
 private:
   virtual bool do_serialize(THD *thd, Out_stream &out_stream);
   virtual void build_drop_statement(String_stream &s_stream) const;
@@ -915,11 +922,16 @@ private:
 class Database_item_obj : public Abstract_obj
 {
 public:
-  inline Database_item_obj(LEX_STRING db_name, LEX_STRING object_name)
-    : Abstract_obj(object_name)
+  inline Database_item_obj(LEX_STRING db_name, LEX_STRING object_name, 
+                           bool lc_name= FALSE)
+    : Abstract_obj(object_name, lc_name)
   {
     if (db_name.str && db_name.length)
+    {
       m_db_name.copy(db_name.str, db_name.length, system_charset_info);
+      if (lc_name)
+        my_casedn_str(system_charset_info, m_db_name.c_ptr());
+    }
     else
       m_db_name.length(0);
   }
@@ -966,9 +978,12 @@ public:
   { }
 
   inline Table_obj(LEX_STRING db_name, LEX_STRING table_name)
-    : Database_item_obj(db_name, table_name)
+    : Database_item_obj(db_name, table_name, lower_case_table_names == 1)
   { }
 
+  virtual inline bool is_my_name(const String *name) const 
+  { return is_my_name_lctn(name); }
+
 private:
   virtual bool do_serialize(THD *thd, Out_stream &out_stream);
 
@@ -1005,11 +1020,15 @@ public:
     : Database_item_obj(db_name, view_name)
   { }
 
+  virtual inline bool is_my_name(const String *name) const 
+  { return is_my_name_lctn(name); }
+
 private:
   virtual bool do_serialize(THD *thd, Out_stream &out_stream);
 
   virtual inline const LEX_STRING *get_type_name() const
   { return &View_obj::TYPE_NAME; }
+
 };
 
 ///////////////////////////////////////////////////////////////////////////
@@ -1087,6 +1106,9 @@ public:
     : Stored_routine_obj(db_name, trigger_name)
   { }
 
+  virtual inline bool is_my_name(const String *name) const 
+  { return is_my_name_lctn(name); }
+
 private:
   virtual inline const LEX_STRING *get_type_name() const
   { return &Trigger_obj::TYPE_NAME; }
@@ -2860,110 +2882,69 @@ Obj_iterator* get_view_base_views(THD *t
 ///////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////
 
-Obj *get_database(const String *db_name,
-                  uint image_version,
-                  const String *image)
+Obj *get_database(const String *db_name)
 {
-  return Abstract_obj::init_obj_from_image(
-    new Database_obj(db_name->lex_string()),
-    image_version, image);
+  return new Database_obj(db_name->lex_string());
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
-Obj *get_table(const String *db_name,
-               const String *table_name,
-               uint image_version,
-               const String *image)
+Obj *get_table(const String *db_name, const String *table_name)
 {
-  return Abstract_obj::init_obj_from_image(
-    new Table_obj(db_name->lex_string(), table_name->lex_string()),
-    image_version, image);
+  return new Table_obj(db_name->lex_string(), table_name->lex_string());
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
-Obj *get_view(const String *db_name,
-              const String *view_name,
-              uint image_version,
-              const String *image)
+Obj *get_view(const String *db_name, const String *view_name)
 {
-  return Abstract_obj::init_obj_from_image(
-    new View_obj(db_name->lex_string(), view_name->lex_string()),
-    image_version, image);
+  return new View_obj(db_name->lex_string(), view_name->lex_string());
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
-Obj *get_trigger(const String *db_name,
-                 const String *trigger_name,
-                 uint image_version,
-                 const String *image)
+Obj *get_trigger(const String *db_name, const String *trigger_name)
 {
-  return Abstract_obj::init_obj_from_image(
-    new Trigger_obj(db_name->lex_string(), trigger_name->lex_string()),
-    image_version, image);
+  return new Trigger_obj(db_name->lex_string(), trigger_name->lex_string());
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
-Obj *get_stored_procedure(const String *db_name,
-                          const String *sp_name,
-                          uint image_version,
-                          const String *image)
+Obj *get_stored_procedure(const String *db_name, const String *sp_name)
 {
-  return Abstract_obj::init_obj_from_image(
-    new Stored_proc_obj(db_name->lex_string(), sp_name->lex_string()),
-    image_version, image);
+  return new Stored_proc_obj(db_name->lex_string(), sp_name->lex_string());
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
-Obj *get_stored_function(const String *db_name,
-                         const String *sf_name,
-                         uint image_version,
-                         const String *image)
+Obj *get_stored_function(const String *db_name, const String *sf_name)
 {
-  return Abstract_obj::init_obj_from_image(
-    new Stored_func_obj(db_name->lex_string(), sf_name->lex_string()),
-    image_version, image);
+  return new Stored_func_obj(db_name->lex_string(), sf_name->lex_string());
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
 #ifdef HAVE_EVENT_SCHEDULER
 
-Obj *get_event(const String *db_name,
-               const String *event_name,
-               uint image_version,
-               const String *image)
-{
-  return Abstract_obj::init_obj_from_image(
-    new Event_obj(db_name->lex_string(), event_name->lex_string()),
-    image_version, image);
+Obj *get_event(const String *db_name, const String *event_name)
+{
+  return new Event_obj(db_name->lex_string(), event_name->lex_string());
 }
 
 #endif
 
 ///////////////////////////////////////////////////////////////////////////
 
-Obj *get_tablespace(const String *ts_name,
-                    uint image_version,
-                    const String *image)
+Obj *get_tablespace(const String *ts_name)
 {
-  return Abstract_obj::init_obj_from_image(
-    new Tablespace_obj(ts_name->lex_string()), image_version, image);
+  return new Tablespace_obj(ts_name->lex_string());
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
-Obj *get_db_grant(const String *db_name,
-                  const String *name,
-                  uint image_version,
-                  const String *image)
+Obj *get_db_grant(const String *db_name, const String *name)
 {
-  return Abstract_obj::init_obj_from_image(
-    new Grant_obj(name->lex_string()), image_version, image);
+  return new Grant_obj(name->lex_string());
 }
 
 ///////////////////////////////////////////////////////////////////////////

=== modified file 'sql/si_objects.h'
--- a/sql/si_objects.h	2009-11-26 09:52:48 +0000
+++ b/sql/si_objects.h	2009-12-10 11:24:07 +0000
@@ -63,6 +63,9 @@ public:
   */
   virtual const String *get_db_name() const = 0;
 
+  /// Determine if given name refers to this object.
+  virtual bool is_my_name(const String *name) const = 0;
+
 public:
   /**
     Serialize an object to an image. The serialization image is opaque
@@ -76,6 +79,17 @@ public:
   */
   virtual bool serialize(THD *thd, String *image) = 0;
 
+  /** 
+    Init this object instance with serialization image so that it is ready
+    for creation.
+
+    @param[in] image_version  Serialization image version number.
+    @param[in] image          Serialization image.
+
+    @return TRUE upon error, FALSE otherwise.
+  */
+  virtual bool init_from_image(uint image_version, const String *image) = 0;
+
   /**
     Create an object persistently in the database.
 
@@ -313,48 +327,15 @@ Obj_iterator* get_view_base_views(THD *t
 
 ///////////////////////////////////////////////////////////////////////////
 
-Obj *get_database(const String *db_name,
-                  uint image_version,
-                  const String *image);
-
-Obj *get_table(const String *db_name,
-               const String *table_name,
-               uint image_version,
-               const String *image);
-
-Obj *get_view(const String *db_name,
-              const String *view_name,
-              uint image_version,
-              const String *image);
-
-Obj *get_trigger(const String *db_name,
-                 const String *trigger_name,
-                 uint image_version,
-                 const String *image);
-
-Obj *get_stored_procedure(const String *db_name,
-                          const String *stored_proc_name,
-                          uint image_version,
-                          const String *image);
-
-Obj *get_stored_function(const String *db_name,
-                         const String *stored_func_name,
-                         uint image_version,
-                         const String *image);
-
-Obj *get_event(const String *db_name,
-               const String *event_name,
-               uint image_version,
-               const String *image);
-
-Obj *get_tablespace(const String *ts_name,
-                    uint image_version,
-                    const String *image);
-
-Obj *get_db_grant(const String *db_name,
-                  const String *name,
-                  uint image_version,
-                  const String *image);
+Obj *get_database(const String *db_name);
+Obj *get_table(const String *db_name, const String *table_name);
+Obj *get_view(const String *db_name, const String *view_name);
+Obj *get_trigger(const String *db_name, const String *trigger_name);
+Obj *get_stored_procedure(const String *db_name, const String *sproc_name);
+Obj *get_stored_function(const String *db_name, const String *sfunc_name);
+Obj *get_event(const String *db_name, const String *event_name);
+Obj *get_tablespace(const String *ts_name);
+Obj *get_db_grant(const String *db_name, const String *name);
 
 ///////////////////////////////////////////////////////////////////////////
 

Attachment: [text/bzr-bundle] bzr/rafal.somla@sun.com-20091210112407-ztkbqpx1rrjj06kc.bundle
Thread
bzr commit into mysql-6.0-backup branch (Rafal.Somla:2903) Bug#43596Rafal Somla10 Dec