#At file:///localhome/jl208045/mysql/mysql-6.0-backup-39063/
2792 Jorgen Loland 2009-03-10
Bug#39063 - Online Backup: Backup behavior changes with the case used for the
database name
Before, the database list for BACKUP was case sensitive. This caused problems in
case insensitive servers because database 'X' and 'x' is considered the same database
while backup would fail if the wrong case was used.
With this patch, the database names are converted to lower case when BACKUP is
executed on a case insensitive server.
added:
mysql-test/suite/backup/r/backup_dbname_lctn1.result
mysql-test/suite/backup/r/backup_dbname_lctn2.result
mysql-test/suite/backup/r/backup_dbname_notwin.result
mysql-test/suite/backup/t/backup_dbname_lctn1-master.opt
mysql-test/suite/backup/t/backup_dbname_lctn1.test
mysql-test/suite/backup/t/backup_dbname_lctn2-master.opt
mysql-test/suite/backup/t/backup_dbname_lctn2.test
mysql-test/suite/backup/t/backup_dbname_notwin.test
modified:
mysql-test/suite/backup/r/backup_errors.result
mysql-test/suite/backup/r/backup_errors_compression.result
mysql-test/suite/backup/t/backup_errors.test
sql/backup/backup_info.cc
sql/backup/backup_test.cc
sql/si_objects.cc
sql/si_objects.h
sql/sql_lex.cc
per-file messages:
mysql-test/suite/backup/r/backup_dbname_lctn1.result
Test BACKUP with different database name cases (upper/lower) in a case insensitive server.
mysql-test/suite/backup/r/backup_dbname_lctn2.result
Test BACKUP with different database name cases (upper/lower) in a case insensitive server with lower_case_table_names=2.
mysql-test/suite/backup/r/backup_dbname_notwin.result
Test BACKUP with different database name cases (upper/lower) in a case sensitive server.
mysql-test/suite/backup/r/backup_errors.result
Make test reflect minor changes to how non-unique database names in BACKUP command works. Also add BACKUP test with error injection into si_object#get_database_stub code
mysql-test/suite/backup/r/backup_errors_compression.result
Make test reflect minor changes to how non-unique database names in BACKUP command works. Also add BACKUP test with error injection into si_object#get_database_stub code
mysql-test/suite/backup/t/backup_dbname_lctn1-master.opt
Test BACKUP with different database name cases (upper/lower) in a case insensitive server.
mysql-test/suite/backup/t/backup_dbname_lctn1.test
Test BACKUP with different database name cases (upper/lower) in a case insensitive server.
mysql-test/suite/backup/t/backup_dbname_lctn2-master.opt
Test BACKUP with different database name cases (upper/lower) in a case insensitive server with lower_case_table_names=2.
mysql-test/suite/backup/t/backup_dbname_lctn2.test
Test BACKUP with different database name cases (upper/lower) in a case insensitive server with lower_case_table_names=2.
mysql-test/suite/backup/t/backup_dbname_notwin.test
Test BACKUP with different database name cases (upper/lower) in a case sensitive server.
mysql-test/suite/backup/t/backup_errors.test
Make test reflect minor changes to how non-unique database names in BACKUP command works. Also add BACKUP test with error injection into si_object#get_database_stub code
sql/backup/backup_info.cc
Error if database name list to the BACKUP command contains non-unique names.
sql/backup/backup_test.cc
Reflect change to si_object#get_database_stub signature.
sql/si_objects.cc
Normalize the database name before creating a database object on servers with case insensitive database names.
sql/si_objects.h
get_database_stub signature changed: THD added as parameter
sql/sql_lex.cc
Remove check of unique database name for BACKUP command. This check is now performed in backup_info.cc.
=== added file 'mysql-test/suite/backup/r/backup_dbname_lctn1.result'
--- a/mysql-test/suite/backup/r/backup_dbname_lctn1.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/r/backup_dbname_lctn1.result 2009-03-10 10:02:06 +0000
@@ -0,0 +1,248 @@
+#
+# Create two database:
+# * 1 with lower-case name "lower"
+# * 1 with upper-case name "UPPER"
+#
+# (Not supposed to be same name)
+DROP DATABASE IF EXISTS lower;
+DROP DATABASE IF EXISTS UPPER;
+# Creating database with lower-case name
+CREATE DATABASE lower;
+CREATE TABLE lower.lcase (a char(10), b char(10)) ENGINE=MEMORY;
+INSERT INTO lower.lcase VALUES ('L41','1300'),
+('L01','1453'),
+('L00','1000'),
+('L41','1301'),
+('L41','1305');
+# Creating database with upper-case name
+CREATE DATABASE UPPER;
+CREATE TABLE UPPER.ucase (a char(10), b char(10)) ENGINE=MEMORY;
+INSERT INTO UPPER.ucase VALUES ('U41','1300'),
+('U01','1453'),
+('U00','1000'),
+('U41','1301'),
+('U41','1305');
+
+# BACKUP lower-case database
+BACKUP DATABASE lower to 'lowlow.bup';
+backup_id
+#
+
+# BACKUP lower-case database using upper-case name
+BACKUP DATABASE LOWER to 'lowup.bup';
+backup_id
+#
+
+# BACKUP upper-case database
+BACKUP DATABASE UPPER to 'upup.bup';
+backup_id
+#
+
+# BACKUP upper-case database using lower-case name
+BACKUP DATABASE upper to 'uplow.bup';
+backup_id
+#
+
+# BACKUP both databases using only lower-case names
+BACKUP DATABASE upper, lower to 'bothcases.bup';
+backup_id
+#
+#
+# Print contents of the databases
+#
+# Lower case database:
+#
+SHOW DATABASES WHERE `Database` LIKE 'lower';
+Database
+lower
+SHOW TABLES IN lower;
+Tables_in_lower
+lcase
+SELECT * FROM lower.lcase;
+a b
+L41 1300
+L01 1453
+L00 1000
+L41 1301
+L41 1305
+#
+# Upper case database:
+#
+SHOW DATABASES WHERE `Database` LIKE 'UPPER';
+Database
+upper
+SHOW TABLES IN UPPER;
+Tables_in_upper
+ucase
+SELECT * FROM UPPER.ucase;
+a b
+U41 1300
+U01 1453
+U00 1000
+U41 1301
+U41 1305
+#
+# Drop the databases
+#
+DROP TABLE lower.lcase;
+DROP TABLE UPPER.ucase;
+DROP DATABASE lower;
+DROP DATABASE UPPER;
+#
+# RESTORE databases with correct case
+#
+# RESTORE lower case database and verify content
+#
+RESTORE FROM 'lowlow.bup';
+backup_id
+#
+
+SHOW DATABASES WHERE `Database` LIKE 'lower';
+Database
+lower
+SHOW TABLES IN lower;
+Tables_in_lower
+lcase
+SELECT * FROM lower.lcase;
+a b
+L41 1300
+L01 1453
+L00 1000
+L41 1301
+L41 1305
+#
+# RESTORE upper case database and verify content
+#
+RESTORE FROM 'upup.bup';
+backup_id
+#
+
+SHOW DATABASES WHERE `Database` LIKE 'UPPER';
+Database
+upper
+SHOW TABLES IN UPPER;
+Tables_in_upper
+ucase
+SELECT * FROM UPPER.ucase;
+a b
+U41 1300
+U01 1453
+U00 1000
+U41 1301
+U41 1305
+#
+# Drop the databases
+#
+DROP TABLE lower.lcase;
+DROP TABLE UPPER.ucase;
+DROP DATABASE lower;
+DROP DATABASE UPPER;
+#
+# RESTORE databases with inverted case
+#
+# RESTORE lower case database and verify content
+#
+RESTORE FROM 'lowup.bup';
+backup_id
+#
+
+SHOW DATABASES WHERE `Database` LIKE 'lower';
+Database
+lower
+SHOW TABLES IN lower;
+Tables_in_lower
+lcase
+SELECT * FROM lower.lcase;
+a b
+L41 1300
+L01 1453
+L00 1000
+L41 1301
+L41 1305
+#
+# RESTORE upper case database and verify content
+#
+RESTORE FROM 'uplow.bup';
+backup_id
+#
+
+SHOW DATABASES WHERE `Database` LIKE 'UPPER';
+Database
+upper
+SHOW TABLES IN UPPER;
+Tables_in_upper
+ucase
+SELECT * FROM UPPER.ucase;
+a b
+U41 1300
+U01 1453
+U00 1000
+U41 1301
+U41 1305
+#
+# Drop the databases
+#
+DROP TABLE lower.lcase;
+DROP TABLE UPPER.ucase;
+DROP DATABASE lower;
+DROP DATABASE UPPER;
+#
+# RESTORE backup image with both databases and verify content
+#
+RESTORE FROM 'bothcases.bup';
+backup_id
+#
+
+SHOW DATABASES WHERE `Database` LIKE 'lower';
+Database
+lower
+SHOW TABLES IN lower;
+Tables_in_lower
+lcase
+SELECT * FROM lower.lcase;
+a b
+L41 1300
+L01 1453
+L00 1000
+L41 1301
+L41 1305
+
+SHOW DATABASES WHERE `Database` LIKE 'UPPER';
+Database
+upper
+SHOW TABLES IN UPPER;
+Tables_in_upper
+ucase
+SELECT * FROM UPPER.ucase;
+a b
+U41 1300
+U01 1453
+U00 1000
+U41 1301
+U41 1305
+#
+# Verify that BACKUP errors if the same database is written twice,
+# but with different case
+#
+BACKUP DATABASE upper, UPPER to 'notunique.bup';
+ERROR 42000: Not unique database: 'upper'
+SHOW WARNINGS;
+Level Code Message
+Error 1753 Not unique database: 'upper'
+Warning 1763 Operation aborted
+#
+# Verify that BACKUP error message has lower case dbname when not found
+#
+BACKUP DATABASE NoTThErE to 'notthere.bup';
+ERROR 42000: Unknown database 'notthere'
+SHOW WARNINGS;
+Level Code Message
+Error 1049 Unknown database 'notthere'
+Warning 1763 Operation aborted
+#
+# CLEANUP
+#
+DROP TABLE lower.lcase;
+DROP TABLE UPPER.ucase;
+DROP DATABASE lower;
+DROP DATABASE UPPER;
=== added file 'mysql-test/suite/backup/r/backup_dbname_lctn2.result'
--- a/mysql-test/suite/backup/r/backup_dbname_lctn2.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/r/backup_dbname_lctn2.result 2009-03-10 10:02:06 +0000
@@ -0,0 +1,233 @@
+#
+# Create two database:
+# * 1 with lower-case name "lower"
+# * 1 with upper-case name "UPPER"
+#
+# (Not supposed to be same name)
+DROP DATABASE IF EXISTS lower;
+DROP DATABASE IF EXISTS UPPER;
+# Creating database with lower-case name
+CREATE DATABASE lower;
+CREATE TABLE lower.lcase (a char(10), b char(10)) ENGINE=MEMORY;
+INSERT INTO lower.lcase VALUES ('L41','1300'),
+('L01','1453'),
+('L00','1000'),
+('L41','1301'),
+('L41','1305');
+# Creating database with upper-case name
+CREATE DATABASE UPPER;
+CREATE TABLE UPPER.ucase (a char(10), b char(10)) ENGINE=MEMORY;
+INSERT INTO UPPER.ucase VALUES ('U41','1300'),
+('U01','1453'),
+('U00','1000'),
+('U41','1301'),
+('U41','1305');
+
+# BACKUP lower-case database
+BACKUP DATABASE lower to 'lowlow.bup';
+backup_id
+#
+
+# BACKUP lower-case database using upper-case name
+BACKUP DATABASE LOWER to 'lowup.bup';
+backup_id
+#
+
+# BACKUP upper-case database
+BACKUP DATABASE UPPER to 'upup.bup';
+backup_id
+#
+
+# BACKUP upper-case database using lower-case name
+BACKUP DATABASE upper to 'uplow.bup';
+backup_id
+#
+
+# BACKUP both databases using only lower-case names
+BACKUP DATABASE upper, lower to 'bothcases.bup';
+backup_id
+#
+#
+# Print contents of the databases
+#
+# Lower case database:
+#
+SHOW DATABASES WHERE `Database` LIKE 'lower';
+Database
+lower
+SHOW TABLES IN lower;
+Tables_in_lower
+lcase
+SELECT * FROM lower.lcase;
+a b
+L41 1300
+L01 1453
+L00 1000
+L41 1301
+L41 1305
+#
+# Upper case database:
+#
+SHOW DATABASES WHERE `Database` LIKE 'UPPER';
+Database
+UPPER
+SHOW TABLES IN UPPER;
+Tables_in_upper
+ucase
+SELECT * FROM UPPER.ucase;
+a b
+U41 1300
+U01 1453
+U00 1000
+U41 1301
+U41 1305
+#
+# Drop the databases
+#
+DROP TABLE lower.lcase;
+DROP TABLE UPPER.ucase;
+DROP DATABASE lower;
+DROP DATABASE UPPER;
+#
+# RESTORE databases with correct case
+#
+# RESTORE lower case database and verify content
+#
+RESTORE FROM 'lowlow.bup';
+backup_id
+#
+
+SHOW DATABASES WHERE `Database` LIKE 'lower';
+Database
+lower
+SHOW TABLES IN lower;
+Tables_in_lower
+lcase
+SELECT * FROM lower.lcase;
+a b
+L41 1300
+L01 1453
+L00 1000
+L41 1301
+L41 1305
+#
+# RESTORE upper case database and verify content
+#
+RESTORE FROM 'upup.bup';
+backup_id
+#
+
+SHOW DATABASES WHERE `Database` LIKE 'UPPER';
+Database
+UPPER
+SHOW TABLES IN UPPER;
+Tables_in_upper
+ucase
+SELECT * FROM UPPER.ucase;
+a b
+#
+# Drop the databases
+#
+DROP TABLE lower.lcase;
+DROP TABLE UPPER.ucase;
+DROP DATABASE lower;
+DROP DATABASE UPPER;
+#
+# RESTORE databases with inverted case
+#
+# RESTORE lower case database and verify content
+#
+RESTORE FROM 'lowup.bup';
+backup_id
+#
+
+SHOW DATABASES WHERE `Database` LIKE 'lower';
+Database
+lower
+SHOW TABLES IN lower;
+Tables_in_lower
+lcase
+SELECT * FROM lower.lcase;
+a b
+L41 1300
+L01 1453
+L00 1000
+L41 1301
+L41 1305
+#
+# RESTORE upper case database and verify content
+#
+RESTORE FROM 'uplow.bup';
+backup_id
+#
+
+SHOW DATABASES WHERE `Database` LIKE 'UPPER';
+Database
+UPPER
+SHOW TABLES IN UPPER;
+Tables_in_upper
+ucase
+SELECT * FROM UPPER.ucase;
+a b
+#
+# Drop the databases
+#
+DROP TABLE lower.lcase;
+DROP TABLE UPPER.ucase;
+DROP DATABASE lower;
+DROP DATABASE UPPER;
+#
+# RESTORE backup image with both databases and verify content
+#
+RESTORE FROM 'bothcases.bup';
+backup_id
+#
+
+SHOW DATABASES WHERE `Database` LIKE 'lower';
+Database
+lower
+SHOW TABLES IN lower;
+Tables_in_lower
+lcase
+SELECT * FROM lower.lcase;
+a b
+L41 1300
+L01 1453
+L00 1000
+L41 1301
+L41 1305
+
+SHOW DATABASES WHERE `Database` LIKE 'UPPER';
+Database
+UPPER
+SHOW TABLES IN UPPER;
+Tables_in_upper
+ucase
+SELECT * FROM UPPER.ucase;
+a b
+#
+# Verify that BACKUP errors if the same database is written twice,
+# but with different case
+#
+BACKUP DATABASE upper, UPPER to 'notunique.bup';
+ERROR 42000: Not unique database: 'UPPER'
+SHOW WARNINGS;
+Level Code Message
+Error 1753 Not unique database: 'UPPER'
+Warning 1763 Operation aborted
+#
+# Verify that BACKUP error message has lower case dbname when not found
+#
+BACKUP DATABASE NoTThErE to 'notthere.bup';
+ERROR 42000: Unknown database 'NoTThErE'
+SHOW WARNINGS;
+Level Code Message
+Error 1049 Unknown database 'NoTThErE'
+Warning 1763 Operation aborted
+#
+# CLEANUP
+#
+DROP TABLE lower.lcase;
+DROP TABLE UPPER.ucase;
+DROP DATABASE lower;
+DROP DATABASE UPPER;
=== added file 'mysql-test/suite/backup/r/backup_dbname_notwin.result'
--- a/mysql-test/suite/backup/r/backup_dbname_notwin.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/r/backup_dbname_notwin.result 2009-03-10 10:02:06 +0000
@@ -0,0 +1,154 @@
+#
+# Create two database:
+# * 1 with lower-case name "backupcasetest"
+# * 1 with upper-case name "BACKUPCASETEST"
+#
+DROP DATABASE IF EXISTS backupcasetest;
+DROP DATABASE IF EXISTS BACKUPCASETEST;
+# Creating database with lower-case name
+CREATE DATABASE backupcasetest;
+CREATE TABLE backupcasetest.lcase (a char(10), b char(10));
+INSERT INTO backupcasetest.lcase VALUES ('L41','1300'),
+('L01','1453'),
+('L00','1000'),
+('L41','1301'),
+('L41','1305');
+# Creating database with upper-case name
+CREATE DATABASE BACKUPCASETEST;
+CREATE TABLE BACKUPCASETEST.ucase (a char(10), b char(10));
+INSERT INTO BACKUPCASETEST.ucase VALUES ('U41','1300'),
+('U01','1453'),
+('U00','1000'),
+('U41','1301'),
+('U41','1305');
+
+# BACKUP lower-case database
+BACKUP DATABASE backupcasetest to 'lcase.bup';
+backup_id
+#
+
+# BACKUP upper-case database
+BACKUP DATABASE BACKUPCASETEST to 'ucase.bup';
+backup_id
+#
+
+# BACKUP both database
+BACKUP DATABASE BACKUPCASETEST, backupcasetest to 'bothcases.bup';
+backup_id
+#
+#
+# Print contents of the databases
+#
+# Lower case database:
+#
+SHOW TABLES IN backupcasetest;
+Tables_in_backupcasetest
+lcase
+SELECT * FROM backupcasetest.lcase;
+a b
+L41 1300
+L01 1453
+L00 1000
+L41 1301
+L41 1305
+#
+# Upper case database:
+#
+SHOW TABLES IN BACKUPCASETEST;
+Tables_in_BACKUPCASETEST
+ucase
+SELECT * FROM BACKUPCASETEST.ucase;
+a b
+U41 1300
+U01 1453
+U00 1000
+U41 1301
+U41 1305
+#
+# Drop the databases
+#
+DROP DATABASE backupcasetest;
+DROP DATABASE BACKUPCASETEST;
+#
+# RESTORE lower case database and verify content
+#
+RESTORE FROM 'lcase.bup';
+backup_id
+#
+
+SHOW DATABASES WHERE `Database` LIKE 'backupcasetest';
+Database
+backupcasetest
+SHOW TABLES IN backupcasetest;
+Tables_in_backupcasetest
+lcase
+SELECT * FROM backupcasetest.lcase;
+a b
+L41 1300
+L01 1453
+L00 1000
+L41 1301
+L41 1305
+#
+# RESTORE upper case database and verify content
+#
+RESTORE FROM 'ucase.bup';
+backup_id
+#
+
+SHOW DATABASES WHERE `Database` LIKE 'backupcasetest';
+Database
+BACKUPCASETEST
+backupcasetest
+SHOW TABLES IN BACKUPCASETEST;
+Tables_in_BACKUPCASETEST
+ucase
+SELECT * FROM BACKUPCASETEST.ucase;
+a b
+U41 1300
+U01 1453
+U00 1000
+U41 1301
+U41 1305
+#
+# Drop the databases
+#
+DROP DATABASE backupcasetest;
+DROP DATABASE BACKUPCASETEST;
+#
+# RESTORE backup image with both databases and verify content
+#
+RESTORE FROM 'bothcases.bup';
+backup_id
+#
+
+SHOW DATABASES WHERE `Database` LIKE 'backupcasetest';
+Database
+BACKUPCASETEST
+backupcasetest
+SHOW TABLES IN backupcasetest;
+Tables_in_backupcasetest
+lcase
+SELECT * FROM backupcasetest.lcase;
+a b
+L41 1300
+L01 1453
+L00 1000
+L41 1301
+L41 1305
+
+SHOW TABLES IN BACKUPCASETEST;
+Tables_in_BACKUPCASETEST
+ucase
+SELECT * FROM BACKUPCASETEST.ucase;
+a b
+U41 1300
+U01 1453
+U00 1000
+U41 1301
+U41 1305
+#
+# CLEANUP
+#
+DROP DATABASE backupcasetest;
+DROP DATABASE BACKUPCASETEST;
=== modified file 'mysql-test/suite/backup/r/backup_errors.result'
--- a/mysql-test/suite/backup/r/backup_errors.result 2009-02-20 00:04:53 +0000
+++ b/mysql-test/suite/backup/r/backup_errors.result 2009-03-10 10:02:06 +0000
@@ -112,17 +112,30 @@ running
Unknown database 'foo,bar'
error
PURGE BACKUP LOGS;
+CREATE DATABASE foo;
+CREATE DATABASE bar;
+#
# repeated database
-BACKUP DATABASE foo,test,bar,foo TO 'test.bak' ;
+#
+BACKUP DATABASE foo, bar, foo TO 'test.bak' ;
ERROR 42000: Not unique database: 'foo'
SHOW WARNINGS;
Level Code Message
Error # Not unique database: 'foo'
+Warning # Operation aborted
verify backup history and progress logs for backup_state.
SELECT backup_state,operation, backup_file, command FROM mysql.backup_history;
backup_state operation backup_file command
+error backup test.bak BACKUP DATABASE foo, bar, foo TO 'test.bak'
SELECT notes FROM mysql.backup_progress;
notes
+starting
+running
+Not unique database: 'foo'
+error
+DROP DATABASE foo;
+DROP DATABASE bar;
+PURGE BACKUP LOGS;
use adb;
create table t1 (a int);
create procedure p1() backup database test to 'test.bak';
@@ -569,6 +582,16 @@ RESTORE FROM 'errorinject.bak';
ERROR HY000: Error when reading summary section of backup image
SET SESSION DEBUG='-d';
#
+# Test error handling by injecting errors into BACKUP
+#
+#
+# Error injection in si_object.cc:get_database_stub
+#
+SET SESSION DEBUG='+d,siobj_get_db_stub';
+BACKUP DATABASE db1 TO 'failed1.bak';
+ERROR HY000: Failed to add database `db1` to the catalog
+SET SESSION DEBUG='-d';
+#
# Cleanup
#
DROP DATABASE db1;
=== modified file 'mysql-test/suite/backup/r/backup_errors_compression.result'
--- a/mysql-test/suite/backup/r/backup_errors_compression.result 2009-02-20 00:04:53 +0000
+++ b/mysql-test/suite/backup/r/backup_errors_compression.result 2009-03-10 10:02:06 +0000
@@ -112,17 +112,30 @@ running
Unknown database 'foo,bar'
error
PURGE BACKUP LOGS;
+CREATE DATABASE foo;
+CREATE DATABASE bar;
+#
# repeated database
-BACKUP DATABASE foo,test,bar,foo TO 'test.bak' WITH COMPRESSION;
+#
+BACKUP DATABASE foo, bar, foo TO 'test.bak' WITH COMPRESSION;
ERROR 42000: Not unique database: 'foo'
SHOW WARNINGS;
Level Code Message
Error # Not unique database: 'foo'
+Warning # Operation aborted
verify backup history and progress logs for backup_state.
SELECT backup_state,operation, backup_file, command FROM mysql.backup_history;
backup_state operation backup_file command
+error backup test.bak BACKUP DATABASE foo, bar, foo TO 'test.bak' WITH COMPRESSION
SELECT notes FROM mysql.backup_progress;
notes
+starting
+running
+Not unique database: 'foo'
+error
+DROP DATABASE foo;
+DROP DATABASE bar;
+PURGE BACKUP LOGS;
use adb;
create table t1 (a int);
create procedure p1() backup database test to 'test.bak';
@@ -569,6 +582,16 @@ RESTORE FROM 'errorinject.bak';
ERROR HY000: Error when reading summary section of backup image
SET SESSION DEBUG='-d';
#
+# Test error handling by injecting errors into BACKUP
+#
+#
+# Error injection in si_object.cc:get_database_stub
+#
+SET SESSION DEBUG='+d,siobj_get_db_stub';
+BACKUP DATABASE db1 TO 'failed1.bak';
+ERROR HY000: Failed to add database `db1` to the catalog
+SET SESSION DEBUG='-d';
+#
# Cleanup
#
DROP DATABASE db1;
=== added file 'mysql-test/suite/backup/t/backup_dbname_lctn1-master.opt'
--- a/mysql-test/suite/backup/t/backup_dbname_lctn1-master.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_dbname_lctn1-master.opt 2009-03-10 10:02:06 +0000
@@ -0,0 +1 @@
+--lower_case_table_names=1
=== added file 'mysql-test/suite/backup/t/backup_dbname_lctn1.test'
--- a/mysql-test/suite/backup/t/backup_dbname_lctn1.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_dbname_lctn1.test 2009-03-10 10:02:06 +0000
@@ -0,0 +1,202 @@
+#
+# Test BACKUP/RESTORE on case-insensitive servers. In this
+# environment, databases 'X' and 'x' are the same database. The
+# database name case used in the BACKUP command should not make a
+# difference. For this test, lower_case_table_names=1.
+#
+
+--source include/not_embedded.inc
+
+--echo #
+--echo # Create two database:
+--echo # * 1 with lower-case name "lower"
+--echo # * 1 with upper-case name "UPPER"
+--echo #
+--echo # (Not supposed to be same name)
+
+--disable_warnings
+DROP DATABASE IF EXISTS lower;
+DROP DATABASE IF EXISTS UPPER;
+--enable_warnings
+
+--echo # Creating database with lower-case name
+CREATE DATABASE lower;
+CREATE TABLE lower.lcase (a char(10), b char(10)) ENGINE=MEMORY;
+INSERT INTO lower.lcase VALUES ('L41','1300'),
+ ('L01','1453'),
+ ('L00','1000'),
+ ('L41','1301'),
+ ('L41','1305');
+
+--echo # Creating database with upper-case name
+CREATE DATABASE UPPER;
+CREATE TABLE UPPER.ucase (a char(10), b char(10)) ENGINE=MEMORY;
+INSERT INTO UPPER.ucase VALUES ('U41','1300'),
+ ('U01','1453'),
+ ('U00','1000'),
+ ('U41','1301'),
+ ('U41','1305');
+
+--echo
+--echo # BACKUP lower-case database
+--replace_column 1 #
+BACKUP DATABASE lower to 'lowlow.bup';
+
+--echo
+--echo # BACKUP lower-case database using upper-case name
+--replace_column 1 #
+BACKUP DATABASE LOWER to 'lowup.bup';
+
+--echo
+--echo # BACKUP upper-case database
+--replace_column 1 #
+BACKUP DATABASE UPPER to 'upup.bup';
+
+--echo
+--echo # BACKUP upper-case database using lower-case name
+--replace_column 1 #
+BACKUP DATABASE upper to 'uplow.bup';
+
+--echo
+--echo # BACKUP both databases using only lower-case names
+--replace_column 1 #
+BACKUP DATABASE upper, lower to 'bothcases.bup';
+
+--echo #
+--echo # Print contents of the databases
+--echo #
+--echo # Lower case database:
+--echo #
+
+SHOW DATABASES WHERE `Database` LIKE 'lower';
+SHOW TABLES IN lower;
+SELECT * FROM lower.lcase;
+
+--echo #
+--echo # Upper case database:
+--echo #
+
+SHOW DATABASES WHERE `Database` LIKE 'UPPER';
+SHOW TABLES IN UPPER;
+SELECT * FROM UPPER.ucase;
+
+--echo #
+--echo # Drop the databases
+--echo #
+DROP TABLE lower.lcase;
+DROP TABLE UPPER.ucase;
+DROP DATABASE lower;
+DROP DATABASE UPPER;
+
+--echo #
+--echo # RESTORE databases with correct case
+--echo #
+--echo # RESTORE lower case database and verify content
+--echo #
+--replace_column 1 #
+RESTORE FROM 'lowlow.bup';
+
+--echo
+SHOW DATABASES WHERE `Database` LIKE 'lower';
+SHOW TABLES IN lower;
+SELECT * FROM lower.lcase;
+
+--echo #
+--echo # RESTORE upper case database and verify content
+--echo #
+--replace_column 1 #
+RESTORE FROM 'upup.bup';
+
+--echo
+SHOW DATABASES WHERE `Database` LIKE 'UPPER';
+SHOW TABLES IN UPPER;
+SELECT * FROM UPPER.ucase;
+
+--echo #
+--echo # Drop the databases
+--echo #
+DROP TABLE lower.lcase;
+DROP TABLE UPPER.ucase;
+DROP DATABASE lower;
+DROP DATABASE UPPER;
+
+--echo #
+--echo # RESTORE databases with inverted case
+--echo #
+--echo # RESTORE lower case database and verify content
+--echo #
+--replace_column 1 #
+RESTORE FROM 'lowup.bup';
+
+--echo
+SHOW DATABASES WHERE `Database` LIKE 'lower';
+SHOW TABLES IN lower;
+SELECT * FROM lower.lcase;
+
+--echo #
+--echo # RESTORE upper case database and verify content
+--echo #
+--replace_column 1 #
+RESTORE FROM 'uplow.bup';
+
+--echo
+SHOW DATABASES WHERE `Database` LIKE 'UPPER';
+SHOW TABLES IN UPPER;
+SELECT * FROM UPPER.ucase;
+
+--echo #
+--echo # Drop the databases
+--echo #
+DROP TABLE lower.lcase;
+DROP TABLE UPPER.ucase;
+DROP DATABASE lower;
+DROP DATABASE UPPER;
+
+--echo #
+--echo # RESTORE backup image with both databases and verify content
+--echo #
+--replace_column 1 #
+RESTORE FROM 'bothcases.bup';
+
+--echo
+SHOW DATABASES WHERE `Database` LIKE 'lower';
+SHOW TABLES IN lower;
+SELECT * FROM lower.lcase;
+
+--echo
+SHOW DATABASES WHERE `Database` LIKE 'UPPER';
+SHOW TABLES IN UPPER;
+SELECT * FROM UPPER.ucase;
+
+--echo #
+--echo # Verify that BACKUP errors if the same database is written twice,
+--echo # but with different case
+--echo #
+
+--error ER_NONUNIQ_DB
+BACKUP DATABASE upper, UPPER to 'notunique.bup';
+SHOW WARNINGS;
+
+--echo #
+--echo # Verify that BACKUP error message has lower case dbname when not found
+--echo #
+
+--error ER_BAD_DB_ERROR
+BACKUP DATABASE NoTThErE to 'notthere.bup';
+SHOW WARNINGS;
+
+--echo #
+--echo # CLEANUP
+--echo #
+DROP TABLE lower.lcase;
+DROP TABLE UPPER.ucase;
+DROP DATABASE lower;
+DROP DATABASE UPPER;
+
+let $MYSQLD_DATADIR = `select @@datadir`;
+--remove_file $MYSQLD_DATADIR/lowlow.bup
+--remove_file $MYSQLD_DATADIR/upup.bup
+--remove_file $MYSQLD_DATADIR/lowup.bup
+--remove_file $MYSQLD_DATADIR/uplow.bup
+--remove_file $MYSQLD_DATADIR/bothcases.bup
+
=== added file 'mysql-test/suite/backup/t/backup_dbname_lctn2-master.opt'
--- a/mysql-test/suite/backup/t/backup_dbname_lctn2-master.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_dbname_lctn2-master.opt 2009-03-10 10:02:06 +0000
@@ -0,0 +1 @@
+--lower_case_table_names=2
=== added file 'mysql-test/suite/backup/t/backup_dbname_lctn2.test'
--- a/mysql-test/suite/backup/t/backup_dbname_lctn2.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_dbname_lctn2.test 2009-03-10 10:02:06 +0000
@@ -0,0 +1,8 @@
+#
+# This test is designed to ensure the backup can successfully
+# backup and retore databases with upper case names when the
+# --lower_case_table_names = 2 on the Windows platform.
+#
+
+--source include/windows.inc
+--source suite/backup/t/backup_dbname_lctn1.test
=== added file 'mysql-test/suite/backup/t/backup_dbname_notwin.test'
--- a/mysql-test/suite/backup/t/backup_dbname_notwin.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_dbname_notwin.test 2009-03-10 10:02:06 +0000
@@ -0,0 +1,129 @@
+#
+# Test BACKUP/RESTORE on case-sensitive servers. In this environment,
+# databases 'X' and 'x' are two different databases that can be backed
+# up and restore independently.
+#
+
+--source include/not_embedded.inc
+--source include/not_windows.inc
+
+--echo #
+--echo # Create two database:
+--echo # * 1 with lower-case name "backupcasetest"
+--echo # * 1 with upper-case name "BACKUPCASETEST"
+--echo #
+
+--disable_warnings
+DROP DATABASE IF EXISTS backupcasetest;
+DROP DATABASE IF EXISTS BACKUPCASETEST;
+--enable_warnings
+
+--echo # Creating database with lower-case name
+CREATE DATABASE backupcasetest;
+CREATE TABLE backupcasetest.lcase (a char(10), b char(10));
+INSERT INTO backupcasetest.lcase VALUES ('L41','1300'),
+ ('L01','1453'),
+ ('L00','1000'),
+ ('L41','1301'),
+ ('L41','1305');
+
+--echo # Creating database with upper-case name
+CREATE DATABASE BACKUPCASETEST;
+CREATE TABLE BACKUPCASETEST.ucase (a char(10), b char(10));
+INSERT INTO BACKUPCASETEST.ucase VALUES ('U41','1300'),
+ ('U01','1453'),
+ ('U00','1000'),
+ ('U41','1301'),
+ ('U41','1305');
+
+--echo
+--echo # BACKUP lower-case database
+--replace_column 1 #
+BACKUP DATABASE backupcasetest to 'lcase.bup';
+
+--echo
+--echo # BACKUP upper-case database
+--replace_column 1 #
+BACKUP DATABASE BACKUPCASETEST to 'ucase.bup';
+
+--echo
+--echo # BACKUP both database
+--replace_column 1 #
+BACKUP DATABASE BACKUPCASETEST, backupcasetest to 'bothcases.bup';
+
+--echo #
+--echo # Print contents of the databases
+--echo #
+--echo # Lower case database:
+--echo #
+
+SHOW TABLES IN backupcasetest;
+SELECT * FROM backupcasetest.lcase;
+
+--echo #
+--echo # Upper case database:
+--echo #
+
+SHOW TABLES IN BACKUPCASETEST;
+SELECT * FROM BACKUPCASETEST.ucase;
+
+--echo #
+--echo # Drop the databases
+--echo #
+DROP DATABASE backupcasetest;
+DROP DATABASE BACKUPCASETEST;
+
+--echo #
+--echo # RESTORE lower case database and verify content
+--echo #
+--replace_column 1 #
+RESTORE FROM 'lcase.bup';
+
+--echo
+SHOW DATABASES WHERE `Database` LIKE 'backupcasetest';
+SHOW TABLES IN backupcasetest;
+SELECT * FROM backupcasetest.lcase;
+
+--echo #
+--echo # RESTORE upper case database and verify content
+--echo #
+--replace_column 1 #
+RESTORE FROM 'ucase.bup';
+
+--echo
+SHOW DATABASES WHERE `Database` LIKE 'backupcasetest';
+SHOW TABLES IN BACKUPCASETEST;
+SELECT * FROM BACKUPCASETEST.ucase;
+
+--echo #
+--echo # Drop the databases
+--echo #
+DROP DATABASE backupcasetest;
+DROP DATABASE BACKUPCASETEST;
+
+--echo #
+--echo # RESTORE backup image with both databases and verify content
+--echo #
+--replace_column 1 #
+RESTORE FROM 'bothcases.bup';
+
+--echo
+SHOW DATABASES WHERE `Database` LIKE 'backupcasetest';
+SHOW TABLES IN backupcasetest;
+SELECT * FROM backupcasetest.lcase;
+
+--echo
+SHOW TABLES IN BACKUPCASETEST;
+SELECT * FROM BACKUPCASETEST.ucase;
+
+--echo #
+--echo # CLEANUP
+--echo #
+DROP DATABASE backupcasetest;
+DROP DATABASE BACKUPCASETEST;
+
+let $MYSQLD_DATADIR = `select @@datadir`;
+--remove_file $MYSQLD_DATADIR/lcase.bup
+--remove_file $MYSQLD_DATADIR/ucase.bup
+--remove_file $MYSQLD_DATADIR/bothcases.bup
+
=== modified file 'mysql-test/suite/backup/t/backup_errors.test'
--- a/mysql-test/suite/backup/t/backup_errors.test 2009-02-20 00:04:53 +0000
+++ b/mysql-test/suite/backup/t/backup_errors.test 2009-03-10 10:02:06 +0000
@@ -117,14 +117,16 @@ SHOW WARNINGS;
SELECT backup_state,operation,backup_file, command FROM mysql.backup_history;
SELECT notes FROM mysql.backup_progress;
-#
-# Note: the following error is detected on parser level. Thus no
-# backup_id is assigned and nothing is written to backup logs.
-#
PURGE BACKUP LOGS;
+
+CREATE DATABASE foo;
+CREATE DATABASE bar;
+
+--echo #
--echo # repeated database
+--echo #
-- error ER_NONUNIQ_DB
-eval BACKUP DATABASE foo,test,bar,foo TO 'test.bak' $compression;
+eval BACKUP DATABASE foo, bar, foo TO 'test.bak' $compression;
--replace_column 2 #
SHOW WARNINGS;
@@ -132,6 +134,11 @@ SHOW WARNINGS;
SELECT backup_state,operation, backup_file, command FROM mysql.backup_history;
SELECT notes FROM mysql.backup_progress;
+DROP DATABASE foo;
+DROP DATABASE bar;
+
+PURGE BACKUP LOGS;
+
# Test that BACKUP/RESTORE statements are disable inside stored routines,
# triggers and events.
@@ -679,6 +686,19 @@ SET SESSION DEBUG='+d,restore_read_summa
RESTORE FROM 'errorinject.bak';
SET SESSION DEBUG='-d';
+
+--echo #
+--echo # Test error handling by injecting errors into BACKUP
+--echo #
+
+--echo #
+--echo # Error injection in si_object.cc:get_database_stub
+--echo #
+SET SESSION DEBUG='+d,siobj_get_db_stub';
+--error ER_BACKUP_CATALOG_ADD_DB
+BACKUP DATABASE db1 TO 'failed1.bak';
+SET SESSION DEBUG='-d';
+
--echo #
--echo # Cleanup
--echo #
=== modified file 'sql/backup/backup_info.cc'
--- a/sql/backup/backup_info.cc 2009-03-02 16:46:01 +0000
+++ b/sql/backup/backup_info.cc 2009-03-10 10:02:06 +0000
@@ -641,47 +641,59 @@ int Backup_info::add_dbs(THD *thd, List<
{
backup::String db_name(*s);
- // Ignore the database if it has already been inserted into the catalogue.
- if (has_db(db_name))
- continue;
-
if (is_internal_db_name(&db_name))
{
m_log.report_error(ER_BACKUP_CANNOT_INCLUDE_DB, db_name.c_ptr());
goto error;
}
- obs::Obj *obj= get_database_stub(&db_name); // reports errors
+ obs::Obj *obj= get_database_stub(thd, &db_name); // reports errors
+
+ if (!obj)
+ {
+ m_log.report_error(ER_BACKUP_CATALOG_ADD_DB, db_name.c_ptr());
+ goto error;
+ }
- if (obj && !check_db_existence(thd, &db_name))
- {
- if (!unknown_dbs.is_empty()) // we just compose unknown_dbs list
- {
- delete obj;
- continue;
- }
+ if (check_db_existence(thd, obj->get_db_name()))
+ {
+ if (!unknown_dbs.is_empty())
+ unknown_dbs.append(",");
+ unknown_dbs.append(obj->get_db_name()->ptr());
- Db *db= add_db(obj); // reports errors
+ delete obj;
+ continue;
+ }
+ else if (!unknown_dbs.is_empty()) // we just compose unknown_dbs list
+ {
+ delete obj;
+ continue;
+ }
- if (!db)
- {
- delete obj;
- goto error;
- }
- if (add_db_items(*db)) // reports errors
- goto error;
+ // Normalize DB name; if case insensitive server, obj->get_db_name
+ // returns name in lower case
+ db_name= obj->get_db_name()->ptr();
+
+ // Error if the same database is requested twice in the database list
+ if (has_db(db_name))
+ {
+ m_log.report_error(ER_NONUNIQ_DB, db_name.c_ptr());;
+ delete obj;
+ goto error;
}
- else if (obj)
+
+ Db *db= add_db(obj); // reports errors
+
+ if (!db)
{
- if (!unknown_dbs.is_empty())
- unknown_dbs.append(",");
- unknown_dbs.append(*obj->get_name());
-
delete obj;
+ goto error;
}
- else
- goto error; // error was reported in get_database()
+
+ if (add_db_items(*db)) // reports errors
+ goto error;
+
}
if (!unknown_dbs.is_empty())
=== modified file 'sql/backup/backup_test.cc'
--- a/sql/backup/backup_test.cc 2008-12-18 21:46:36 +0000
+++ b/sql/backup/backup_test.cc 2009-03-10 10:02:06 +0000
@@ -57,7 +57,7 @@ int execute_backup_test_command(THD *thd
{
String dir;
dir.copy(dbname->str, dbname->length, system_charset_info);
- db= get_database_stub(&dir);
+ db= get_database_stub(thd, &dir);
if (is_internal_db_name(db->get_db_name()))
continue;
=== modified file 'sql/si_objects.cc'
--- a/sql/si_objects.cc 2009-03-09 14:00:03 +0000
+++ b/sql/si_objects.cc 2009-03-10 10:02:06 +0000
@@ -2318,9 +2318,65 @@ bool Grant_obj::do_init_from_image(In_st
///////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
-Obj *get_database_stub(const String *db_name)
+Obj *get_database_stub(THD *thd, const String *db_name)
{
- return new Database_obj(db_name->lex_string());
+
+ DBUG_EXECUTE_IF("siobj_get_db_stub", return NULL; );
+ /*
+ The specified db name may have characters in a wrong case. Get the
+ normalized name by reading it from INFORMATION_SCHEMA. Note: if
+ lower_case_table_names=0, the db name must not be converted.
+ */
+
+ if (!lower_case_table_names)
+ return new Database_obj(db_name->lex_string());
+
+
+ Ed_connection ed_connection(thd);
+ String_stream s_stream;
+ Ed_result_set *ed_result_set;
+
+ // Prepare SELECT statement.
+
+ s_stream << "SELECT schema_name "
+ "FROM INFORMATION_SCHEMA.SCHEMATA WHERE "
+ "LCASE(schema_name) = LCASE('" << db_name << "')";
+
+ // Execute SELECT.
+
+ if (run_service_interface_sql(thd, &ed_connection, s_stream.lex_string()) ||
+ ed_connection.get_warn_count())
+ return NULL;
+
+ // Fetch result.
+
+ ed_result_set= ed_connection.use_result_set();
+
+ // The database did not find the database. Return a Database_obj
+ // with correct name anyway as per method specification
+ if (ed_result_set->size() != 1)
+ {
+ // Need to convert the name to lower case when lctn=1
+ if (lower_case_table_names == 1)
+ {
+ String lcasename;
+ lcasename.copy(db_name->ptr(), db_name->length(), system_charset_info);
+ my_casedn_str(lcasename.charset(), lcasename.c_ptr());
+ return new Database_obj(lcasename.lex_string());
+ }
+ else
+ return new Database_obj(db_name->lex_string());
+ }
+
+ List_iterator_fast<Ed_row> row_it(*ed_result_set);
+ Ed_row *row= row_it++;
+
+ DBUG_ASSERT(row->size() == 1);
+
+
+ // Create object using normalized name.
+
+ return new Database_obj(*row);
}
///////////////////////////////////////////////////////////////////////////
=== modified file 'sql/si_objects.h'
--- a/sql/si_objects.h 2009-02-13 13:25:43 +0000
+++ b/sql/si_objects.h 2009-03-10 10:02:06 +0000
@@ -152,7 +152,7 @@ public:
@return a pointer to an instance of Obj representing the given database.
*/
-Obj *get_database_stub(const String *db_name);
+Obj *get_database_stub(THD *thd, const String *db_name);
///////////////////////////////////////////////////////////////////////////
=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc 2009-02-05 12:49:39 +0000
+++ b/sql/sql_lex.cc 2009-03-10 10:02:06 +0000
@@ -3031,19 +3031,7 @@ int LEX::add_db_to_list(LEX_STRING *name
{
DBUG_ASSERT(name);
- List_iterator<LEX_STRING> it(db_list);
- LEX_STRING *copy;
-
- while ((copy= it++))
- if (!my_strnncoll(system_charset_info,
- (const uchar*) name->str, name->length ,
- (const uchar*) copy->str, copy->length ))
- {
- my_error(ER_NONUNIQ_DB, MYF(0), name->str);
- return ER_NONUNIQ_DB;
- }
-
- copy= (LEX_STRING*) sql_memdup(name, sizeof(LEX_STRING));
+ LEX_STRING *copy= (LEX_STRING*) sql_memdup(name, sizeof(LEX_STRING));
if (copy == NULL)
return ER_OUT_OF_RESOURCES;