List:Commits« Previous MessageNext Message »
From:Georgi Kodinov Date:September 10 2008 2:50pm
Subject:bzr commit into mysql-6.0 branch (kgeorge:2828)
View as plain text  
#At file:///home/kgeorge/mysql/bzr/merge-6.0-main-6.0-bugteam/

 2828 Georgi Kodinov	2008-09-10 [merge]
      merged 6.0 main to 6.0-bugteam
removed:
  mysql-test/r/log_bin_trust_routine_creators_basic.result
  mysql-test/t/log_bin_trust_routine_creators_basic.test
added:
  mysql-test/r/backup_db_grants.result
  mysql-test/r/backup_default.result
  mysql-test/r/backup_timeout.result
  mysql-test/t/backup_db_grants.test
  mysql-test/t/backup_default.test
  mysql-test/t/backup_timeout.test
modified:
  .bzr-mysql/default.conf
  configure.in
  mysql-test/lib/mtr_report.pl
  mysql-test/r/backup_errors.result
  mysql-test/r/backup_views.result
  mysql-test/t/backup_errors.test
  mysql-test/t/backup_views.test
  mysql-test/t/disabled.def
  mysql-test/t/union.test
  sql/backup/backup_aux.h
  sql/backup/backup_info.cc
  sql/backup/backup_info.h
  sql/backup/backup_test.cc
  sql/backup/be_default.cc
  sql/backup/image_info.cc
  sql/backup/image_info.h
  sql/backup/kernel.cc
  sql/ddl_blocker.cc
  sql/mysql_priv.h
  sql/set_var.cc
  sql/set_var.h
  sql/share/errmsg.txt
  sql/si_objects.cc
  sql/si_objects.h
  sql/sql_class.cc
  sql/sql_class.h
  sql/sql_parse.cc

=== modified file '.bzr-mysql/default.conf'
--- a/.bzr-mysql/default.conf	2008-09-10 10:40:14 +0000
+++ b/.bzr-mysql/default.conf	2008-09-10 12:50:02 +0000
@@ -1,5 +1,5 @@
-[MYSQL]
-tree_location = bzr+ssh://bk-internal.mysql.com/bzrroot/server/mysql-6.0
-post_commit_to = commits@stripped
-post_push_to = commits@stripped
-tree_name = mysql-6.0
+[MYSQL]
+tree_location = bzr+ssh://bk-internal.mysql.com/bzrroot/server/mysql-6.0
+post_commit_to = commits@stripped.com
+post_push_to = commits@stripped
+tree_name = mysql-6.0

=== modified file 'configure.in'
--- a/configure.in	2008-09-10 10:40:14 +0000
+++ b/configure.in	2008-09-10 12:50:02 +0000
@@ -9,7 +9,7 @@ AC_CANONICAL_SYSTEM
 # remember to also update version.c in ndb
 # When changing major version number please also check switch statement
 # in mysqlbinlog::check_master_version().
-AM_INIT_AUTOMAKE(mysql, 6.0.7-alpha)
+AM_INIT_AUTOMAKE(mysql, 6.0.8-alpha)
 AM_CONFIG_HEADER([include/config.h:config.h.in])
 
 NDB_VERSION_MAJOR=6

=== modified file 'mysql-test/lib/mtr_report.pl'
--- a/mysql-test/lib/mtr_report.pl	2008-08-25 14:26:49 +0000
+++ b/mysql-test/lib/mtr_report.pl	2008-09-04 13:46:04 +0000
@@ -346,6 +346,12 @@ sub mtr_report_stats ($) {
 		  /Can't execute this command because another BACKUP\/RESTORE operation is in progress/
 		) or
                 
+		# backup_db_grants test is supposed to trigger lots of restore warnings
+		($testname eq 'main.backup_db_grants') and
+		(
+		  /Restore:/ or /was skipped because the user does not exist/
+		) or
+                
 		# The tablespace test triggers error below on purpose
 		($testname eq 'main.backup_tablespace') and
 		(

=== added file 'mysql-test/r/backup_db_grants.result'
--- a/mysql-test/r/backup_db_grants.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/backup_db_grants.result	2008-08-25 18:14:40 +0000
@@ -0,0 +1,183 @@
+DROP DATABASE IF EXISTS bup_db_grants;
+DROP DATABASE IF EXISTS db2;
+Create two databases and two tables.
+CREATE DATABASE bup_db_grants;
+CREATE DATABASE db2;
+CREATE TABLE bup_db_grants.t1(a INT);
+CREATE TABLE bup_db_grants.s1(b INT);
+INSERT INTO bup_db_grants.t1 VALUES (1), (2), (3), (4);
+INSERT INTO bup_db_grants.s1 VALUES (10), (20), (30), (40);
+Now create users and assign various rights to the databases
+CREATE USER 'bup_user1'@'%';
+CREATE USER bup_user2;
+CREATE USER 'bup_user3'@'%';
+REVOKE ALL ON *.* FROM 'bup_user1'@'%';
+REVOKE ALL ON *.* FROM bup_user2;
+GRANT ALL ON db2.* TO 'bup_user1'@'%';
+GRANT SELECT ON bup_db_grants.* TO 'bup_user1'@'%';
+GRANT INSERT ON bup_db_grants.* TO bup_user2;
+GRANT ALL ON bup_db_grants.* TO 'no_user'@'%';
+GRANT SELECT (a) ON bup_db_grants.t1 TO 'bup_user1'@'%';
+GRANT SELECT (b), INSERT (b) ON bup_db_grants.s1 TO bup_user2;
+FLUSH PRIVILEGES;
+Demonstrate rights of the users.
+SHOW GRANTS FOR 'bup_user1'@'%';
+Grants for bup_user1@%
+GRANT USAGE ON *.* TO 'bup_user1'@'%'
+GRANT ALL PRIVILEGES ON `db2`.* TO 'bup_user1'@'%'
+GRANT SELECT ON `bup_db_grants`.* TO 'bup_user1'@'%'
+GRANT SELECT (a) ON `bup_db_grants`.`t1` TO 'bup_user1'@'%'
+SHOW GRANTS FOR bup_user2;
+Grants for bup_user2@%
+GRANT USAGE ON *.* TO 'bup_user2'@'%'
+GRANT INSERT ON `bup_db_grants`.* TO 'bup_user2'@'%'
+GRANT SELECT (b), INSERT (b) ON `bup_db_grants`.`s1` TO 'bup_user2'@'%'
+SHOW GRANTS FOR 'bup_user3'@'%';
+Grants for bup_user3@%
+GRANT USAGE ON *.* TO 'bup_user3'@'%'
+SHOW GRANTS FOR 'no_user'@'%';
+Grants for no_user@%
+GRANT USAGE ON *.* TO 'no_user'@'%'
+GRANT ALL PRIVILEGES ON `bup_db_grants`.* TO 'no_user'@'%'
+Run backup
+BACKUP DATABASE bup_db_grants TO 'bup_db_grants.bak';
+backup_id
+#
+Drop users and recreate them (removes grants completely).
+DROP USER 'bup_user1'@'%';
+DROP USER bup_user2;
+DROP USER 'bup_user3'@'%';
+DROP USER 'no_user'@'%';
+FLUSH PRIVILEGES;
+CREATE USER 'bup_user1'@'%';
+CREATE USER bup_user2;
+CREATE USER 'bup_user3'@'%';
+FLUSH PRIVILEGES;
+Demonstrate rights of the users.
+SHOW GRANTS FOR 'bup_user1'@'%';
+Grants for bup_user1@%
+GRANT USAGE ON *.* TO 'bup_user1'@'%'
+SHOW GRANTS FOR bup_user2;
+Grants for bup_user2@%
+GRANT USAGE ON *.* TO 'bup_user2'@'%'
+SHOW GRANTS FOR 'bup_user3'@'%';
+Grants for bup_user3@%
+GRANT USAGE ON *.* TO 'bup_user3'@'%'
+Run Restore
+RESTORE FROM 'bup_db_grants.bak';
+backup_id
+#
+SHOW TABLES FROM bup_db_grants;
+Tables_in_bup_db_grants
+s1
+t1
+Demonstrate rights of the users.
+SHOW GRANTS FOR 'bup_user1'@'%';
+Grants for bup_user1@%
+GRANT USAGE ON *.* TO 'bup_user1'@'%'
+GRANT SELECT ON `bup_db_grants`.* TO 'bup_user1'@'%'
+GRANT SELECT (a) ON `bup_db_grants`.`t1` TO 'bup_user1'@'%'
+SHOW GRANTS FOR bup_user2;
+Grants for bup_user2@%
+GRANT USAGE ON *.* TO 'bup_user2'@'%'
+GRANT INSERT ON `bup_db_grants`.* TO 'bup_user2'@'%'
+GRANT SELECT (b), INSERT (b) ON `bup_db_grants`.`s1` TO 'bup_user2'@'%'
+SHOW GRANTS FOR 'bup_user3'@'%';
+Grants for bup_user3@%
+GRANT USAGE ON *.* TO 'bup_user3'@'%'
+SHOW GRANTS FOR 'no_user'@'%';
+ERROR 42000: There is no such grant defined for user 'no_user' on host '%'
+Now test what happens on backup if users are deleted.
+Drop users and recreate one of them (removes grants completely).
+DROP USER 'bup_user1'@'%';
+DROP USER bup_user2;
+DROP USER 'bup_user3'@'%';
+FLUSH PRIVILEGES;
+CREATE USER 'bup_user1'@'%';
+CREATE USER 'bup_user1'@'nosuchhost';
+Run Restore
+RESTORE FROM 'bup_db_grants.bak';
+backup_id
+#
+SHOW TABLES FROM bup_db_grants;
+Tables_in_bup_db_grants
+s1
+t1
+Demonstrate rights of the users.
+SHOW GRANTS FOR 'bup_user1'@'%';
+Grants for bup_user1@%
+GRANT USAGE ON *.* TO 'bup_user1'@'%'
+GRANT SELECT ON `bup_db_grants`.* TO 'bup_user1'@'%'
+GRANT SELECT (a) ON `bup_db_grants`.`t1` TO 'bup_user1'@'%'
+SHOW GRANTS FOR bup_user2;
+ERROR 42000: There is no such grant defined for user 'bup_user2' on host '%'
+SHOW GRANTS FOR 'bup_user3'@'%';
+ERROR 42000: There is no such grant defined for user 'bup_user3' on host '%'
+SHOW GRANTS FOR 'no_user'@'%';
+ERROR 42000: There is no such grant defined for user 'no_user' on host '%'
+Cleanup
+DROP USER 'bup_user1'@'%';
+DROP USER 'bup_user1'@'nosuchhost';
+DROP USER bup_user2;
+ERROR HY000: Operation DROP USER failed for 'bup_user2'@'%'
+DROP USER 'bup_user3'@'%';
+ERROR HY000: Operation DROP USER failed for 'bup_user3'@'%'
+DROP USER 'no_user'@'%';
+ERROR HY000: Operation DROP USER failed for 'no_user'@'%'
+FLUSH PRIVILEGES;
+Now test for encoded user names with an x40 in the middle.
+SET NAMES sjis;
+DROP DATABASE bup_db_grants;
+Create a database and some tables.
+CREATE DATABASE bup_db_grants;
+CREATE TABLE bup_db_grants.t1(a INT);
+CREATE TABLE bup_db_grants.s1(b INT);
+Create a user with multibyte username with @ in the middle.
+SET @name = CONVERT(0x8340 using sjis);
+SELECT @name;
+@name
+�@
+SET @cmd = CONCAT('CREATE USER ', @name);
+PREPARE stmt1 FROM @cmd;
+EXECUTE stmt1;
+Grant privileges to user.
+SET @cmd = CONCAT('GRANT SELECT ON bup_db_grants.* TO ', @name);
+PREPARE stmt2 from @cmd;
+EXECUTE stmt2;
+FLUSH PRIVILEGES;
+Show existing grants.
+SET @cmd = CONCAT('SHOW GRANTS FOR ', @name);
+PREPARE stmt3 FROM @cmd;
+EXECUTE stmt3;
+Grants for �@@%
+GRANT USAGE ON *.* TO '�@'@'%'
+GRANT SELECT ON `bup_db_grants`.* TO '�@'@'%'
+Backup database.
+BACKUP DATABASE bup_db_grants TO 'bup_db_grants.bak';
+backup_id
+#
+Remove privileges from user.
+SET @cmd = CONCAT('REVOKE ALL ON bup_db_grants.* FROM ', @name);
+PREPARE stmt4 FROM @cmd;
+EXECUTE stmt4;
+FLUSH PRIVILEGES;
+Show existing grants -- should only USAGE.
+EXECUTE stmt3;
+Grants for �@@%
+GRANT USAGE ON *.* TO '�@'@'%'
+Run restore.
+RESTORE FROM 'bup_db_grants.bak';
+backup_id
+#
+FLUSH PRIVILEGES;
+Ensure grants have been restored.
+EXECUTE stmt3;
+Grants for �@@%
+GRANT USAGE ON *.* TO '�@'@'%'
+GRANT SELECT ON `bup_db_grants`.* TO '�@'@'%'
+SET @cmd = CONCAT('DROP USER ', @name);
+PREPARE stmt5 FROM @cmd;
+EXECUTE stmt5;
+SET NAMES latin1;
+DROP DATABASE bup_db_grants;
+DROP DATABASE db2;

=== added file 'mysql-test/r/backup_default.result'
--- a/mysql-test/r/backup_default.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/backup_default.result	2008-08-26 13:28:34 +0000
@@ -0,0 +1,73 @@
+
+Server should not crash for backup using default driver - CSV
+Test for bug#35117
+
+DROP DATABASE IF EXISTS db1;
+CREATE DATABASE db1;
+USE db1;
+CREATE TABLE csv_table(
+id int NOT NULL,
+name char(20) NOT NULL,
+city varchar(20) NOT NULL) 
+ENGINE=csv;
+INSERT INTO csv_table VALUES(1,'aa1','bb1'),(2,'aa2','bb2'),(3,'aa3','bb3');
+backup on csv only
+BACKUP DATABASE db1 to 'bup_csv.bak';
+backup_id
+#
+DROP DATABASE db1;
+restore on csv only
+RESTORE FROM 'bup_csv.bak';
+backup_id
+#
+testing content in restored tables
+SELECT * FROM csv_table ORDER BY id;
+id	name	city
+1	aa1	bb1
+2	aa2	bb2
+3	aa3	bb3
+DROP DATABASE db1;
+
+Server should not crash for backup using default driver 
+Partitioned Falcon tables
+Test for bug#33566, bug#36792 
+
+CREATE DATABASE db1;
+USE db1;
+CREATE TABLE partition_table (
+int_column int(11), 
+char_column char(5))
+engine=falcon
+PARTITION BY HASH (int_column);
+INSERT INTO partition_table VALUES (0,'pVtIa');
+INSERT INTO partition_table VALUES (5,'jTfSg');
+INSERT INTO partition_table VALUES (20,'UezFi');
+INSERT INTO partition_table VALUES (25,'cxmeH');
+INSERT INTO partition_table VALUES (65,'lIuNS');
+testing content in restored tables
+SELECT * FROM partition_table ORDER BY int_column;
+int_column	char_column
+0	pVtIa
+5	jTfSg
+20	UezFi
+25	cxmeH
+65	lIuNS
+
+Server should not crash for backup using default driver 
+Mix of tables
+
+CREATE TABLE csv_table(
+id int NOT NULL,
+name char(20) NOT NULL,
+city varchar(20) NOT NULL) 
+ENGINE=csv;
+INSERT INTO csv_table VALUES(1,'aa1','bb1'),(2,'aa2','bb2'),(3,'aa3','bb3');
+CREATE TABLE myisam_table(
+i int,
+v varchar(20))
+ENGINE=myisam;
+INSERT INTO myisam_table VALUES(1,'v1'),(2,'v2'),(3,'v3');
+
+***  CLEANUP  ****
+
+DROP DATABASE db1;

=== modified file 'mysql-test/r/backup_errors.result'
--- a/mysql-test/r/backup_errors.result	2008-03-05 17:48:12 +0000
+++ b/mysql-test/r/backup_errors.result	2008-08-21 11:36:09 +0000
@@ -95,3 +95,41 @@ Restoring the table
 CREATE TABLE mysql.online_backup_progress LIKE test.obp_copy;
 DROP TABLE test.obp_copy;
 DROP DATABASE test_ob_error;
+
+Bug#38624
+Test that backup fails with error if database files are removed 
+after backup starts
+SET DEBUG_SYNC= 'reset';
+DROP DATABASE IF EXISTS db1;
+CREATE DATABASE db1;
+start backup but stop just before adding metadata to backup image
+SET DEBUG_SYNC= 'backup_before_write_preamble SIGNAL running WAIT_FOR db_will_fail';
+BACKUP DATABASE db1 TO 'bup_db1.bak';
+SET DEBUG_SYNC='now WAIT_FOR running';
+delete database files so that check_db_dir_exists will fail in 
+si_objects.cc @ DatabaseObj::do_serialize
+SET DEBUG_SYNC='now SIGNAL db_will_fail';
+Database has been deleted, backup will fail
+ERROR 42000: Unknown database 'db1'
+
+Test that backup fails with error if a table used by 
+a trigger cannot be opened
+SET DEBUG_SYNC= 'reset';
+DROP DATABASE IF EXISTS db1;
+CREATE DATABASE db1;
+CREATE TABLE db1.t1 (i int);
+CREATE TABLE db1.t2 (v varchar (20));
+CREATE TRIGGER db1.trg AFTER INSERT ON db1.t1 FOR EACH ROW
+BEGIN
+INSERT INTO db1.t2(v) VALUES ('Test trigger fired');   
+END;||
+SET DEBUG_SYNC= 'reset';
+Setting debug point that will make backup fail when adding the
+trigger metadata
+SET SESSION DEBUG='+d,backup_fail_add_trigger';
+BACKUP DATABASE db1 TO 'bup_db1.bak';
+ERROR HY000: Failed to obtain meta-data for trigger `db1`.`trg`
+SET DEBUG_SYNC= 'reset';
+DROP DATABASE db1;
+
+Done testing for Bug#38624

=== added file 'mysql-test/r/backup_timeout.result'
--- a/mysql-test/r/backup_timeout.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/backup_timeout.result	2008-08-19 15:35:29 +0000
@@ -0,0 +1,73 @@
+SET DEBUG_SYNC= 'reset';
+DROP DATABASE IF EXISTS bup_ddl_blocker;
+CREATE DATABASE bup_ddl_blocker;
+con1: Creating tables
+CREATE TABLE bup_ddl_blocker.t1 (col_a CHAR(40)) ENGINE=INNODB;
+con1: Loading data
+INSERT INTO bup_ddl_blocker.t1 VALUES ("01 Some data to test");
+INSERT INTO bup_ddl_blocker.t1 VALUES ("02 Some data to test");
+INSERT INTO bup_ddl_blocker.t1 VALUES ("03 Some data to test");
+SHOW VARIABLES LIKE 'backup_wait%';
+Variable_name	Value
+backup_wait_timeout	50
+Part A
+con1: Activate synchronization points for backup.
+SET DEBUG_SYNC= 'after_block_ddl SIGNAL bup_blocked WAIT_FOR timeout_done';
+con1: Get a backup going and stop after the DDL blocker is fired.
+BACKUP DATABASE bup_ddl_blocker TO "bup_ddl_blocker.bak";
+SET DEBUG_SYNC= 'now WAIT_FOR bup_blocked';
+Set ddl timeout to 1 second
+SET backup_wait_timeout = 1;
+SHOW VARIABLES LIKE 'backup_wait%';
+Variable_name	Value
+backup_wait_timeout	1
+con2: Try a ddl operation and watch it expire
+CREATE TABLE bup_ddl_blocker.t2 (col_a CHAR(40)) ENGINE=MEMORY;
+ERROR HY000: The backup wait timeout has expired for query 'CREATE TABLE bup_ddl_blocker.t2 (col_a CHAR(40)) ENGINE=MEMORY'.
+release the lock.
+con5: Resume all.
+SET DEBUG_SYNC= 'now SIGNAL timeout_done';
+backup_id
+#
+Part B
+con1: Activate synchronization points for backup.
+SET DEBUG_SYNC= 'after_block_ddl SIGNAL bup_blocked WAIT_FOR timeout_done';
+con1: Get a backup going and stop after the DDL blocker is fired.
+BACKUP DATABASE bup_ddl_blocker TO "bup_ddl_blocker.bak";
+SET DEBUG_SYNC= 'now WAIT_FOR bup_blocked';
+Set ddl timeout to 0 seconds
+SET backup_wait_timeout = 0;
+SHOW VARIABLES LIKE 'backup_wait%';
+Variable_name	Value
+backup_wait_timeout	0
+con2: Try a ddl operation and it should expire
+CREATE TABLE bup_ddl_blocker.t3 (col_a CHAR(40)) ENGINE=MEMORY;
+ERROR HY000: The backup wait timeout has expired for query 'CREATE TABLE bup_ddl_blocker.t3 (col_a CHAR(40)) ENGINE=MEMORY'.
+SET backup_wait_timeout = 100;
+SHOW VARIABLES LIKE 'backup_wait%';
+Variable_name	Value
+backup_wait_timeout	100
+con3: Try a ddl operation and it should not expire
+CREATE TABLE bup_ddl_blocker.t3 (col_a CHAR(40)) ENGINE=MEMORY;
+release the lock.
+con5: Resume all.
+SET DEBUG_SYNC= 'now SIGNAL timeout_done';
+backup_id
+#
+USE bup_ddl_blocker;
+SHOW FULL TABLES;
+Tables_in_bup_ddl_blocker	Table_type
+t1	BASE TABLE
+t3	BASE TABLE
+Part C
+Show that the variable can be reset to its timeout value using
+SET backup_wait_timeout = DEFAULT;
+SET backup_wait_timeout = 1;
+SHOW VARIABLES LIKE 'backup_wait%';
+Variable_name	Value
+backup_wait_timeout	1
+SET backup_wait_timeout = DEFAULT;
+SHOW VARIABLES LIKE 'backup_wait%';
+Variable_name	Value
+backup_wait_timeout	50
+DROP DATABASE bup_ddl_blocker;

=== modified file 'mysql-test/r/backup_views.result'
--- a/mysql-test/r/backup_views.result	2008-08-11 10:41:41 +0000
+++ b/mysql-test/r/backup_views.result	2008-08-20 13:23:10 +0000
@@ -277,10 +277,10 @@ DROP DATABASE bup_db2;
 Restore database.
 restore database with view dependency to other, non-existing db
 RESTORE FROM 'bup_objectview1.bak';
-ERROR 42S02: Table 'bup_db2.t2' doesn't exist
+ERROR HY000: Could not restore view `bup_db1`.`v5`. Please check the view definition for possible missing dependencies.
 DROP DATABASE bup_db1;
 RESTORE FROM 'bup_objectview2.bak';
-ERROR 42S02: Table 'bup_db1.t3' doesn't exist
+ERROR HY000: Could not restore view `bup_db2`.`student_details`. Please check the view definition for possible missing dependencies.
 DROP DATABASE bup_db2;
 RESTORE FROM 'bup_objectview.bak';
 backup_id

=== removed file 'mysql-test/r/log_bin_trust_routine_creators_basic.result'
--- a/mysql-test/r/log_bin_trust_routine_creators_basic.result	2008-04-10 13:14:28 +0000
+++ b/mysql-test/r/log_bin_trust_routine_creators_basic.result	1970-01-01 00:00:00 +0000
@@ -1,121 +0,0 @@
-SET @start_global_value = @@global.log_bin_trust_routine_creators;
-SELECT @start_global_value;
-@start_global_value
-1
-'#--------------------FN_DYNVARS_064_01-------------------------#'
-SET @@global.log_bin_trust_routine_creators = TRUE;
-Warnings:
-Warning	1287	The syntax 'log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use 'log_bin_trust_function_creators' instead
-SET @@global.log_bin_trust_routine_creators = DEFAULT;
-Warnings:
-Warning	1287	The syntax 'log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use 'log_bin_trust_function_creators' instead
-SELECT @@global.log_bin_trust_routine_creators;
-@@global.log_bin_trust_routine_creators
-0
-'#--------------------FN_DYNVARS_064_02-------------------------#'
-SET @@global.log_bin_trust_routine_creators = DEFAULT;
-Warnings:
-Warning	1287	The syntax 'log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use 'log_bin_trust_function_creators' instead
-SELECT @@global.log_bin_trust_routine_creators = 'FALSE';
-@@global.log_bin_trust_routine_creators = 'FALSE'
-1
-Warnings:
-Warning	1292	Truncated incorrect DOUBLE value: 'FALSE'
-'#--------------------FN_DYNVARS_064_03-------------------------#'
-SET @@global.log_bin_trust_routine_creators = ON;
-Warnings:
-Warning	1287	The syntax 'log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use 'log_bin_trust_function_creators' instead
-SELECT @@global.log_bin_trust_routine_creators;
-@@global.log_bin_trust_routine_creators
-1
-SET @@global.log_bin_trust_routine_creators = OFF;
-Warnings:
-Warning	1287	The syntax 'log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use 'log_bin_trust_function_creators' instead
-SELECT @@global.log_bin_trust_routine_creators;
-@@global.log_bin_trust_routine_creators
-0
-SET @@global.log_bin_trust_routine_creators = 0;
-Warnings:
-Warning	1287	The syntax 'log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use 'log_bin_trust_function_creators' instead
-SELECT @@global.log_bin_trust_routine_creators;
-@@global.log_bin_trust_routine_creators
-0
-SET @@global.log_bin_trust_routine_creators = 1;
-Warnings:
-Warning	1287	The syntax 'log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use 'log_bin_trust_function_creators' instead
-SELECT @@global.log_bin_trust_routine_creators;
-@@global.log_bin_trust_routine_creators
-1
-SET @@global.log_bin_trust_routine_creators = TRUE;
-Warnings:
-Warning	1287	The syntax 'log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use 'log_bin_trust_function_creators' instead
-SELECT @@global.log_bin_trust_routine_creators;
-@@global.log_bin_trust_routine_creators
-1
-SET @@global.log_bin_trust_routine_creators = FALSE;
-Warnings:
-Warning	1287	The syntax 'log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use 'log_bin_trust_function_creators' instead
-SELECT @@global.log_bin_trust_routine_creators;
-@@global.log_bin_trust_routine_creators
-0
-'#-------------------FN_DYNVARS_064_04----------------------------#'
-SET @@session.log_bin_trust_routine_creators = 0;
-ERROR HY000: Variable 'log_bin_trust_routine_creators' is a GLOBAL variable and should be set with SET GLOBAL
-SELECT @@session.log_bin_trust_routine_creators;
-ERROR HY000: Variable 'log_bin_trust_routine_creators' is a GLOBAL variable
-'#------------------FN_DYNVARS_064_05-----------------------#'
-SET @@global.log_bin_trust_routine_creators = 'ONN';
-ERROR 42000: Variable 'log_bin_trust_routine_creators' can't be set to the value of 'ONN'
-SET @@global.log_bin_trust_routine_creators = "OFFF";
-ERROR 42000: Variable 'log_bin_trust_routine_creators' can't be set to the value of 'OFFF'
-SET @@global.log_bin_trust_routine_creators = OF;
-Warnings:
-Warning	1287	The syntax 'log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use 'log_bin_trust_function_creators' instead
-SELECT @@global.log_bin_trust_routine_creators;
-@@global.log_bin_trust_routine_creators
-0
-'Bug# 34828: OF is also working as OFF and no error is coming';
-SET @@global.log_bin_trust_routine_creators = TTRUE;
-ERROR 42000: Variable 'log_bin_trust_routine_creators' can't be set to the value of 'TTRUE'
-SET @@global.log_bin_trust_routine_creators = FELSE;
-ERROR 42000: Variable 'log_bin_trust_routine_creators' can't be set to the value of 'FELSE'
-SET @@global.log_bin_trust_routine_creators = -1024;
-ERROR 42000: Variable 'log_bin_trust_routine_creators' can't be set to the value of '-1024'
-SET @@global.log_bin_trust_routine_creators = 65536;
-ERROR 42000: Variable 'log_bin_trust_routine_creators' can't be set to the value of '65536'
-SET @@global.log_bin_trust_routine_creators = 65530.34;
-ERROR 42000: Variable 'log_bin_trust_routine_creators' can't be set to the value of '65530'
-SET @@global.log_bin_trust_routine_creators = test;
-ERROR 42000: Variable 'log_bin_trust_routine_creators' can't be set to the value of 'test'
-'#------------------FN_DYNVARS_064_06-----------------------#'
-SELECT @@global.log_bin_trust_routine_creators = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_bin_trust_routine_creators';
-@@global.log_bin_trust_routine_creators = VARIABLE_VALUE
-1
-SELECT @@session.log_bin_trust_routine_creators = VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='log_bin_trust_routine_creators';
-ERROR HY000: Variable 'log_bin_trust_routine_creators' is a GLOBAL variable
-'#---------------------FN_DYNVARS_064_07----------------------#'
-SET @@global.log_bin_trust_routine_creators = TRUE;
-Warnings:
-Warning	1287	The syntax 'log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use 'log_bin_trust_function_creators' instead
-SELECT @@log_bin_trust_routine_creators = @@global.log_bin_trust_routine_creators;
-@@log_bin_trust_routine_creators = @@global.log_bin_trust_routine_creators
-1
-'#---------------------FN_DYNVARS_064_08----------------------#'
-SET @@global.log_bin_trust_routine_creators = TRUE;
-Warnings:
-Warning	1287	The syntax 'log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use 'log_bin_trust_function_creators' instead
-SELECT @@log_bin_trust_routine_creators;
-@@log_bin_trust_routine_creators
-1
-SELECT local.log_bin_trust_routine_creators;
-ERROR 42S02: Unknown table 'local' in field list
-SELECT session.log_bin_trust_routine_creators;
-ERROR 42S02: Unknown table 'session' in field list
-SELECT log_bin_trust_routine_creators = @@session.log_bin_trust_routine_creators;
-ERROR 42S22: Unknown column 'log_bin_trust_routine_creators' in 'field list'
-SET @@global.log_bin_trust_routine_creators = @start_global_value;
-Warnings:
-Warning	1287	The syntax 'log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use 'log_bin_trust_function_creators' instead
-SELECT @@global.log_bin_trust_routine_creators;
-@@global.log_bin_trust_routine_creators
-1

=== added file 'mysql-test/t/backup_db_grants.test'
--- a/mysql-test/t/backup_db_grants.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/backup_db_grants.test	2008-08-25 18:14:40 +0000
@@ -0,0 +1,198 @@
+#
+# Test the backup of database grants
+#
+
+--source include/not_embedded.inc
+--source include/have_sjis.inc
+
+--disable_warnings
+DROP DATABASE IF EXISTS bup_db_grants;
+DROP DATABASE IF EXISTS db2;
+--enable_warnings
+
+--echo Create two databases and two tables.
+CREATE DATABASE bup_db_grants;
+CREATE DATABASE db2;
+CREATE TABLE bup_db_grants.t1(a INT);
+CREATE TABLE bup_db_grants.s1(b INT);
+INSERT INTO bup_db_grants.t1 VALUES (1), (2), (3), (4);
+INSERT INTO bup_db_grants.s1 VALUES (10), (20), (30), (40);
+
+--echo Now create users and assign various rights to the databases
+CREATE USER 'bup_user1'@'%';
+CREATE USER bup_user2;
+CREATE USER 'bup_user3'@'%';
+REVOKE ALL ON *.* FROM 'bup_user1'@'%';
+REVOKE ALL ON *.* FROM bup_user2;
+GRANT ALL ON db2.* TO 'bup_user1'@'%';
+GRANT SELECT ON bup_db_grants.* TO 'bup_user1'@'%';
+GRANT INSERT ON bup_db_grants.* TO bup_user2;
+GRANT ALL ON bup_db_grants.* TO 'no_user'@'%';
+GRANT SELECT (a) ON bup_db_grants.t1 TO 'bup_user1'@'%';
+GRANT SELECT (b), INSERT (b) ON bup_db_grants.s1 TO bup_user2;
+FLUSH PRIVILEGES;
+
+--echo Demonstrate rights of the users.
+SHOW GRANTS FOR 'bup_user1'@'%';
+SHOW GRANTS FOR bup_user2;
+SHOW GRANTS FOR 'bup_user3'@'%';
+SHOW GRANTS FOR 'no_user'@'%';
+
+--echo Run backup
+--replace_column 1 #
+BACKUP DATABASE bup_db_grants TO 'bup_db_grants.bak';
+
+--echo Drop users and recreate them (removes grants completely).
+DROP USER 'bup_user1'@'%';
+DROP USER bup_user2;
+DROP USER 'bup_user3'@'%';
+DROP USER 'no_user'@'%';
+
+FLUSH PRIVILEGES;
+
+CREATE USER 'bup_user1'@'%';
+CREATE USER bup_user2;
+CREATE USER 'bup_user3'@'%';
+
+FLUSH PRIVILEGES;
+
+--echo Demonstrate rights of the users.
+SHOW GRANTS FOR 'bup_user1'@'%';
+SHOW GRANTS FOR bup_user2;
+SHOW GRANTS FOR 'bup_user3'@'%';
+
+--echo Run Restore
+--replace_column 1 #
+RESTORE FROM 'bup_db_grants.bak';
+
+SHOW TABLES FROM bup_db_grants;
+
+--echo Demonstrate rights of the users.
+# Note: Since db2 was not in the backup and the user was deleted prior to 
+# the restore, that privilege will not appear here.
+SHOW GRANTS FOR 'bup_user1'@'%';
+SHOW GRANTS FOR bup_user2;
+SHOW GRANTS FOR 'bup_user3'@'%';
+--error ER_NONEXISTING_GRANT
+SHOW GRANTS FOR 'no_user'@'%';
+
+--echo Now test what happens on backup if users are deleted.
+
+--echo Drop users and recreate one of them (removes grants completely).
+DROP USER 'bup_user1'@'%';
+DROP USER bup_user2;
+DROP USER 'bup_user3'@'%';
+
+FLUSH PRIVILEGES;
+
+CREATE USER 'bup_user1'@'%';
+CREATE USER 'bup_user1'@'nosuchhost';
+
+--echo Run Restore
+--replace_column 1 #
+RESTORE FROM 'bup_db_grants.bak';
+
+SHOW TABLES FROM bup_db_grants;
+
+--echo Demonstrate rights of the users.
+SHOW GRANTS FOR 'bup_user1'@'%';
+--error ER_NONEXISTING_GRANT
+SHOW GRANTS FOR bup_user2;
+--error ER_NONEXISTING_GRANT
+SHOW GRANTS FOR 'bup_user3'@'%';
+--error ER_NONEXISTING_GRANT
+SHOW GRANTS FOR 'no_user'@'%';
+
+#
+# Section of test disabled due to errors in PB. See BUG#39016
+#
+#--echo Now demonstrate what happens when grants are altered in backup image.
+#
+#--exec perl -pi.bak -e "s/ON bup/ON boo/" $MYSQLTEST_VARDIR/master-data/bup_db_grants.bak 
+#--echo Run Restore
+#--error ER_BACKUP_GRANT_WRONG_DB
+#RESTORE FROM 'bup_db_grants.bak';
+#
+#FLUSH PRIVILEGES;
+
+--echo Cleanup
+
+DROP USER 'bup_user1'@'%';
+DROP USER 'bup_user1'@'nosuchhost';
+--error ER_CANNOT_USER
+DROP USER bup_user2;
+--error ER_CANNOT_USER
+DROP USER 'bup_user3'@'%';
+--error ER_CANNOT_USER
+DROP USER 'no_user'@'%';
+
+FLUSH PRIVILEGES;
+
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_db_grants.bak
+
+#--remove_file $MYSQLTEST_VARDIR/master-data/bup_db_grants.bak.bak
+
+--echo Now test for encoded user names with an x40 in the middle.
+
+SET NAMES sjis;
+
+DROP DATABASE bup_db_grants;
+
+--echo Create a database and some tables.
+CREATE DATABASE bup_db_grants;
+CREATE TABLE bup_db_grants.t1(a INT);
+CREATE TABLE bup_db_grants.s1(b INT);
+
+--echo Create a user with multibyte username with @ in the middle.
+SET @name = CONVERT(0x8340 using sjis);
+SELECT @name;
+SET @cmd = CONCAT('CREATE USER ', @name);
+PREPARE stmt1 FROM @cmd;
+EXECUTE stmt1;
+
+--echo Grant privileges to user.
+SET @cmd = CONCAT('GRANT SELECT ON bup_db_grants.* TO ', @name);
+PREPARE stmt2 from @cmd;
+EXECUTE stmt2;
+
+FLUSH PRIVILEGES;
+
+--echo Show existing grants.
+SET @cmd = CONCAT('SHOW GRANTS FOR ', @name);
+PREPARE stmt3 FROM @cmd;
+EXECUTE stmt3;
+
+--echo Backup database.
+--replace_column 1 #
+BACKUP DATABASE bup_db_grants TO 'bup_db_grants.bak';
+
+--echo Remove privileges from user.
+SET @cmd = CONCAT('REVOKE ALL ON bup_db_grants.* FROM ', @name);
+PREPARE stmt4 FROM @cmd;
+EXECUTE stmt4;
+
+FLUSH PRIVILEGES;
+
+--echo Show existing grants -- should only USAGE.
+EXECUTE stmt3;
+
+--echo Run restore.
+--replace_column 1 #
+RESTORE FROM 'bup_db_grants.bak';
+
+FLUSH PRIVILEGES;
+
+--echo Ensure grants have been restored.
+EXECUTE stmt3;
+
+SET @cmd = CONCAT('DROP USER ', @name);
+PREPARE stmt5 FROM @cmd;
+EXECUTE stmt5;
+
+SET NAMES latin1;
+
+DROP DATABASE bup_db_grants;
+DROP DATABASE db2;
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_db_grants.bak

=== added file 'mysql-test/t/backup_default.test'
--- a/mysql-test/t/backup_default.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/backup_default.test	2008-08-26 13:28:34 +0000
@@ -0,0 +1,136 @@
+###########################################################################
+# Purpose: To test backup using default driver
+###############################################################################
+--source include/have_falcon.inc
+--source include/have_partition.inc
+--source include/not_embedded.inc
+
+--echo
+--echo Server should not crash for backup using default driver - CSV
+--echo Test for bug#35117
+--echo
+
+--disable_warnings
+DROP DATABASE IF EXISTS db1;
+--enable_warnings
+
+CREATE DATABASE db1;
+USE db1;
+
+# csv uses default driver
+CREATE TABLE csv_table(
+   id int NOT NULL,
+   name char(20) NOT NULL,
+   city varchar(20) NOT NULL) 
+ENGINE=csv;
+
+INSERT INTO csv_table VALUES(1,'aa1','bb1'),(2,'aa2','bb2'),(3,'aa3','bb3');
+
+--echo backup on csv only
+--replace_column 1 #
+BACKUP DATABASE db1 to 'bup_csv.bak';
+
+DROP DATABASE db1;
+
+--echo restore on csv only
+--replace_column 1 #
+RESTORE FROM 'bup_csv.bak';
+
+--echo testing content in restored tables
+SELECT * FROM csv_table ORDER BY id;
+
+DROP DATABASE db1;
+
+--echo
+--echo Server should not crash for backup using default driver 
+--echo Partitioned Falcon tables
+--echo Test for bug#33566, bug#36792 
+--echo 
+
+CREATE DATABASE db1;
+USE db1;
+
+CREATE TABLE partition_table (
+  int_column int(11), 
+  char_column char(5))
+engine=falcon
+PARTITION BY HASH (int_column);
+
+INSERT INTO partition_table VALUES (0,'pVtIa');
+INSERT INTO partition_table VALUES (5,'jTfSg');
+INSERT INTO partition_table VALUES (20,'UezFi');
+INSERT INTO partition_table VALUES (25,'cxmeH');
+INSERT INTO partition_table VALUES (65,'lIuNS');
+
+#
+# This portion of the test has been disabled. See BUG#39017
+#
+#--echo backup on partitioned falcon
+#--replace_column 1 #
+#BACKUP DATABASE db1 to 'bup_falcon.bak';
+#
+#DROP DATABASE db1;
+#
+#--echo restore on partitioned falcon
+#--replace_column 1 #
+#RESTORE FROM 'bup_falcon.bak';
+
+--echo testing content in restored tables
+SELECT * FROM partition_table ORDER BY int_column;
+
+
+--echo
+--echo Server should not crash for backup using default driver 
+--echo Mix of tables
+--echo 
+
+# partition_table already exists in the database
+# re-create the csv_table
+CREATE TABLE csv_table(
+   id int NOT NULL,
+   name char(20) NOT NULL,
+   city varchar(20) NOT NULL) 
+ENGINE=csv;
+
+INSERT INTO csv_table VALUES(1,'aa1','bb1'),(2,'aa2','bb2'),(3,'aa3','bb3');
+
+# create a myisam table (not default driver)
+CREATE TABLE myisam_table(
+   i int,
+   v varchar(20))
+ENGINE=myisam;
+
+INSERT INTO myisam_table VALUES(1,'v1'),(2,'v2'),(3,'v3');
+
+#
+# This portion of the test has been disabled. See BUG#39017
+#
+#--echo backup on mixed table database
+#--replace_column 1 #
+#BACKUP DATABASE db1 to 'bup_mixed.bak';
+#
+#DROP DATABASE db1;
+#
+#--echo restore on mixed table database
+#--replace_column 1 #
+#RESTORE FROM 'bup_mixed.bak';
+#
+#--echo testing content in restored tables
+#SELECT * FROM partition_table ORDER BY int_column;
+#SELECT * FROM csv_table ORDER BY id;
+#SELECT * FROM myisam_table ORDER BY i;
+
+
+# Test cleanup section
+
+--echo
+--echo ***  CLEANUP  ****
+--echo
+
+
+DROP DATABASE db1;
+
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_csv.bak
+#--remove_file $MYSQLTEST_VARDIR/master-data/bup_falcon.bak
+#--remove_file $MYSQLTEST_VARDIR/master-data/bup_mixed.bak
+

=== modified file 'mysql-test/t/backup_errors.test'
--- a/mysql-test/t/backup_errors.test	2008-03-04 17:09:56 +0000
+++ b/mysql-test/t/backup_errors.test	2008-08-21 11:36:09 +0000
@@ -1,4 +1,6 @@
 --source include/not_embedded.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
 
 # Check that BACKUP/RESTORE commands correctly report errors 
 #
@@ -209,3 +211,82 @@ CREATE TABLE mysql.online_backup_progres
 DROP TABLE test.obp_copy;
 
 DROP DATABASE test_ob_error;
+
+
+--echo
+--echo Bug#38624
+--echo Test that backup fails with error if database files are removed 
+--echo after backup starts
+
+SET DEBUG_SYNC= 'reset';
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+
+connection con1;
+
+--disable_warnings
+DROP DATABASE IF EXISTS db1;
+
+CREATE DATABASE db1;
+
+connection con2;
+
+--echo start backup but stop just before adding metadata to backup image
+SET DEBUG_SYNC= 'backup_before_write_preamble SIGNAL running WAIT_FOR db_will_fail';
+
+send BACKUP DATABASE db1 TO 'bup_db1.bak';
+
+connection con1;
+
+SET DEBUG_SYNC='now WAIT_FOR running';
+
+--echo delete database files so that check_db_dir_exists will fail in 
+--echo si_objects.cc @ DatabaseObj::do_serialize
+
+--remove_file $MYSQLTEST_VARDIR/master-data/db1/db.opt
+--rmdir $MYSQLTEST_VARDIR/master-data/db1
+
+SET DEBUG_SYNC='now SIGNAL db_will_fail';
+
+connection con2;
+--echo Database has been deleted, backup will fail
+--error ER_BAD_DB_ERROR
+reap;
+
+--echo
+--echo Test that backup fails with error if a table used by 
+--echo a trigger cannot be opened
+
+SET DEBUG_SYNC= 'reset';
+
+connection con1;
+
+--disable_warnings
+DROP DATABASE IF EXISTS db1;
+
+CREATE DATABASE db1;
+CREATE TABLE db1.t1 (i int);
+CREATE TABLE db1.t2 (v varchar (20));
+
+DELIMITER ||;
+CREATE TRIGGER db1.trg AFTER INSERT ON db1.t1 FOR EACH ROW
+BEGIN
+  INSERT INTO db1.t2(v) VALUES ('Test trigger fired');   
+END;||
+DELIMITER ;||
+
+SET DEBUG_SYNC= 'reset';
+
+--echo Setting debug point that will make backup fail when adding the
+--echo trigger metadata
+
+SET SESSION DEBUG='+d,backup_fail_add_trigger';
+--error ER_BACKUP_GET_META_TRIGGER
+BACKUP DATABASE db1 TO 'bup_db1.bak';
+
+SET DEBUG_SYNC= 'reset';
+DROP DATABASE db1;
+
+--echo
+--echo Done testing for Bug#38624

=== added file 'mysql-test/t/backup_timeout.test'
--- a/mysql-test/t/backup_timeout.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/backup_timeout.test	2008-08-19 15:35:29 +0000
@@ -0,0 +1,162 @@
+#
+# This test is for the DDL blocker timeout feature.
+#
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/not_embedded.inc
+--source include/have_debug_sync.inc
+
+SET DEBUG_SYNC= 'reset';
+
+#
+# Remove backup files (if they exist)
+#
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_ddl_blocker.bak;
+
+#
+# Connections used in this test
+#
+# con1       used to create data, load data, and run the backup 
+# con2-con4  used for DDL statements: 2 before backup and 2 during backup
+# con5       used for setting and releasing breakpoints
+#
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+connect (con3,localhost,root,,);
+connect (con4,localhost,root,,);
+connect (con5,localhost,root,,);
+
+connection con1;
+
+# Create data for this test and tailor it to the test.
+--disable_warnings
+DROP DATABASE IF EXISTS bup_ddl_blocker;
+--enable_warnings
+
+CREATE DATABASE bup_ddl_blocker;
+
+# Create a table and load it with data.
+--echo con1: Creating tables
+CREATE TABLE bup_ddl_blocker.t1 (col_a CHAR(40)) ENGINE=INNODB;
+
+--echo con1: Loading data
+INSERT INTO bup_ddl_blocker.t1 VALUES ("01 Some data to test");
+INSERT INTO bup_ddl_blocker.t1 VALUES ("02 Some data to test");
+INSERT INTO bup_ddl_blocker.t1 VALUES ("03 Some data to test");
+
+SHOW VARIABLES LIKE 'backup_wait%';
+
+#
+# Part A - test timeout for one session 
+#
+--echo Part A
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_ddl_blocker.bak
+
+connection con1;
+
+--echo con1: Activate synchronization points for backup.
+SET DEBUG_SYNC= 'after_block_ddl SIGNAL bup_blocked WAIT_FOR timeout_done';
+
+--echo con1: Get a backup going and stop after the DDL blocker is fired.
+send BACKUP DATABASE bup_ddl_blocker TO "bup_ddl_blocker.bak";
+
+connection con2;
+
+SET DEBUG_SYNC= 'now WAIT_FOR bup_blocked';
+
+--echo Set ddl timeout to 1 second
+SET backup_wait_timeout = 1; 
+SHOW VARIABLES LIKE 'backup_wait%';
+
+--echo con2: Try a ddl operation and watch it expire
+--error ER_DDL_TIMEOUT
+CREATE TABLE bup_ddl_blocker.t2 (col_a CHAR(40)) ENGINE=MEMORY;
+
+connection con5;
+--echo release the lock.
+--echo con5: Resume all.
+SET DEBUG_SYNC= 'now SIGNAL timeout_done';
+
+# Reconnect to con1 and let backup finish.
+
+connection con1;
+--replace_column 1 #
+reap;
+
+#
+# Part B - test timeout for a session with a timeout, 
+#          and a session with no timeout (backup_wait_timeout = 0)
+#
+--echo Part B
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_ddl_blocker.bak
+
+connection con1;
+
+--echo con1: Activate synchronization points for backup.
+SET DEBUG_SYNC= 'after_block_ddl SIGNAL bup_blocked WAIT_FOR timeout_done';
+
+--echo con1: Get a backup going and stop after the DDL blocker is fired.
+send BACKUP DATABASE bup_ddl_blocker TO "bup_ddl_blocker.bak";
+
+connection con2;
+
+SET DEBUG_SYNC= 'now WAIT_FOR bup_blocked';
+
+--echo Set ddl timeout to 0 seconds
+SET backup_wait_timeout = 0; 
+SHOW VARIABLES LIKE 'backup_wait%';
+
+--echo con2: Try a ddl operation and it should expire
+--error ER_DDL_TIMEOUT
+CREATE TABLE bup_ddl_blocker.t3 (col_a CHAR(40)) ENGINE=MEMORY;
+
+connection con3;
+
+SET backup_wait_timeout = 100;
+SHOW VARIABLES LIKE 'backup_wait%';
+
+--echo con3: Try a ddl operation and it should not expire
+send CREATE TABLE bup_ddl_blocker.t3 (col_a CHAR(40)) ENGINE=MEMORY;
+
+connection con5;
+--echo release the lock.
+--echo con5: Resume all.
+SET DEBUG_SYNC= 'now SIGNAL timeout_done';
+
+# Reconnect to con1 and let backup finish.
+
+connection con1;
+--replace_column 1 #
+reap;
+
+connection con3;
+reap;
+
+USE bup_ddl_blocker;
+SHOW FULL TABLES;
+
+#
+# Part C - test default behavior: set backup timeout = default
+#
+--echo Part C
+
+connection con1;
+
+--echo Show that the variable can be reset to its timeout value using
+--echo SET backup_wait_timeout = DEFAULT;
+SET backup_wait_timeout = 1; 
+SHOW VARIABLES LIKE 'backup_wait%';
+SET backup_wait_timeout = DEFAULT; 
+SHOW VARIABLES LIKE 'backup_wait%';
+
+DROP DATABASE bup_ddl_blocker;
+
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_ddl_blocker.bak

=== modified file 'mysql-test/t/backup_views.test'
--- a/mysql-test/t/backup_views.test	2008-08-11 10:41:41 +0000
+++ b/mysql-test/t/backup_views.test	2008-08-20 13:23:10 +0000
@@ -205,14 +205,14 @@ DROP DATABASE bup_db2;
 
 --echo restore database with view dependency to other, non-existing db
 
---error ER_NO_SUCH_TABLE
+--error ER_BACKUP_CANT_RESTORE_VIEW
 RESTORE FROM 'bup_objectview1.bak';
 
 # An incomplete bup_db1 was created by the failing restore operation.
 # Remove it before trying restore of bup_db2.
 DROP DATABASE bup_db1;
 
---error ER_NO_SUCH_TABLE
+--error ER_BACKUP_CANT_RESTORE_VIEW
 RESTORE FROM 'bup_objectview2.bak';
 
 # An incomplete bup_db2 was created by the failing restore operation.

=== modified file 'mysql-test/t/disabled.def'
--- a/mysql-test/t/disabled.def	2008-09-01 09:28:27 +0000
+++ b/mysql-test/t/disabled.def	2008-09-04 13:46:04 +0000
@@ -17,7 +17,6 @@ lowercase_table3         : Bug#32667 low
 rpl_log_pos          : Bug#8693 Test 'rpl_log_pos' fails sometimes
 ctype_create         : Bug#32965 main.ctype_create fails
 backup_no_engine     : Bug#36021 2008-04-13 rsomla server crashes when openning table with unknown storage engine
-backup_tablespace    : Bug #36973 backup_tablespace.test fails in pushbuild
 csv_alter_table      : Bug#33696 2008-01-21 pcrews no .result file - bug allows NULL columns in CSV tables
 query_cache_wlock_invalidate_func: Bug#35390 causes not deterministic results.
 thread_cache_size_func: BUG#35988, BUG#36733 Due to not deterministic results
@@ -39,6 +38,5 @@ key_buffer_size_basic_32    : Bug#36876 
 max_heap_table_size_basic_32 : Bug#36877 main.max_heap_table_size_basic_32 fails on some systems
 tmp_table_size_basic_32     : Bug#36878 main.tmp_table_size_basic_32 fails on some systems
 backup_triggers_and_events  : Bug#37762 2008-07-01 rafal Test fails on remove_file for unknown reasons
-backup_tablespace           : Bug#36973 2008-07-01 rafal
 backup_no_be                : Bug#38023 2008-07-16 rafal Test triggers valgrind warnings described in the bug
 user_limits                 : Bug#23921 2008-07-25 joro random failure of user_limits.test

=== removed file 'mysql-test/t/log_bin_trust_routine_creators_basic.test'
--- a/mysql-test/t/log_bin_trust_routine_creators_basic.test	2008-04-10 13:14:28 +0000
+++ b/mysql-test/t/log_bin_trust_routine_creators_basic.test	1970-01-01 00:00:00 +0000
@@ -1,164 +0,0 @@
-############## mysql-test\t\log_bin_trust_routine_creators_basic.test #########
-#                                                                             #
-# Variable Name: log_bin_trust_routine_creators                               #
-# Scope: GLOBAL                                                               #
-# Access Type: Dynamic                                                        #
-# Data Type: boolean                                                          #
-# Default Value: False                                                        #
-# Range:                                                                      #
-#                                                                             #
-#                                                                             #
-# Creation Date: 2008-02-12                                                   #
-# Author:  Salman                                                             #
-#                                                                             #
-# Description: Test Cases of Dynamic System Variable                          #
-#              log_bin_trust_routine_creators that checks the                 #
-#              behavior of this variable in the following ways                #
-#              * Default Value                                                #
-#              * Valid & Invalid values                                       #
-#              * Scope & Access method                                        #
-#              * Data Integrity                                               #
-#                                                                             #
-# Reference: (Not given on website)                                           #
-#                                                                             #
-###############################################################################
-
---source include/load_sysvars.inc
-####################################################################
-#   START OF log_bin_trust_routine_creators TESTS                  #
-####################################################################
-
-
-#############################################################
-#                 Save initial value                        #
-#############################################################
-
-SET @start_global_value = @@global.log_bin_trust_routine_creators;
-SELECT @start_global_value;
-
-
---echo '#--------------------FN_DYNVARS_064_01-------------------------#'
-########################################################################
-#     Display the DEFAULT value of log_bin_trust_routine_creators     #
-########################################################################
-
-SET @@global.log_bin_trust_routine_creators = TRUE;
-SET @@global.log_bin_trust_routine_creators = DEFAULT;
-SELECT @@global.log_bin_trust_routine_creators;
-
-
---echo '#--------------------FN_DYNVARS_064_02-------------------------#'
-##############################################################################
-#     Check the DEFAULT value of log_bin_trust_routine_creators              #
-##############################################################################
-
-SET @@global.log_bin_trust_routine_creators = DEFAULT;
-SELECT @@global.log_bin_trust_routine_creators = 'FALSE';
-
-
---echo '#--------------------FN_DYNVARS_064_03-------------------------#'
-##################################################################
-# Change the value of variable to a valid value for GLOBAL Scope #
-##################################################################
-
-SET @@global.log_bin_trust_routine_creators = ON;
-SELECT @@global.log_bin_trust_routine_creators;
-SET @@global.log_bin_trust_routine_creators = OFF;
-SELECT @@global.log_bin_trust_routine_creators;
-SET @@global.log_bin_trust_routine_creators = 0;
-SELECT @@global.log_bin_trust_routine_creators;
-SET @@global.log_bin_trust_routine_creators = 1;
-SELECT @@global.log_bin_trust_routine_creators;
-SET @@global.log_bin_trust_routine_creators = TRUE;
-SELECT @@global.log_bin_trust_routine_creators;
-SET @@global.log_bin_trust_routine_creators = FALSE;
-SELECT @@global.log_bin_trust_routine_creators;
-
-
---echo '#-------------------FN_DYNVARS_064_04----------------------------#'
-########################################################################### 
-#   Test if accessing session log_bin_trust_routine_creators gives error  #
-########################################################################### 
-
---Error ER_GLOBAL_VARIABLE
-SET @@session.log_bin_trust_routine_creators = 0;
---Error ER_INCORRECT_GLOBAL_LOCAL_VAR
-SELECT @@session.log_bin_trust_routine_creators;
-
-
---echo '#------------------FN_DYNVARS_064_05-----------------------#'
-##########################################################################
-# Change the value of log_bin_trust_routine_creators to an invalid value #
-##########################################################################
-
---Error ER_WRONG_VALUE_FOR_VAR
-SET @@global.log_bin_trust_routine_creators = 'ONN';
---Error ER_WRONG_VALUE_FOR_VAR
-SET @@global.log_bin_trust_routine_creators = "OFFF";
-SET @@global.log_bin_trust_routine_creators = OF;
-SELECT @@global.log_bin_trust_routine_creators;
---echo 'Bug# 34828: OF is also working as OFF and no error is coming';
-
---Error ER_WRONG_VALUE_FOR_VAR
-SET @@global.log_bin_trust_routine_creators = TTRUE;
---Error ER_WRONG_VALUE_FOR_VAR
-SET @@global.log_bin_trust_routine_creators = FELSE;
---Error ER_WRONG_VALUE_FOR_VAR
-SET @@global.log_bin_trust_routine_creators = -1024;
---Error ER_WRONG_VALUE_FOR_VAR
-SET @@global.log_bin_trust_routine_creators = 65536;
---Error ER_WRONG_VALUE_FOR_VAR
-SET @@global.log_bin_trust_routine_creators = 65530.34;
---Error ER_WRONG_VALUE_FOR_VAR
-SET @@global.log_bin_trust_routine_creators = test;
-
-
---echo '#------------------FN_DYNVARS_064_06-----------------------#'
-###############################################################################
-#   Check if the value in GLOBAL & SESSION Tables matches value in variable   #
-###############################################################################
-
-
-SELECT @@global.log_bin_trust_routine_creators = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_bin_trust_routine_creators';
-
---Error ER_INCORRECT_GLOBAL_LOCAL_VAR
-SELECT @@session.log_bin_trust_routine_creators = VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='log_bin_trust_routine_creators';
-
-
---echo '#---------------------FN_DYNVARS_064_07----------------------#'
-#################################################################################
-#  Check if accessing variable with and without GLOBAL point to same variable   #
-#################################################################################
-
-
-SET @@global.log_bin_trust_routine_creators = TRUE;
-SELECT @@log_bin_trust_routine_creators = @@global.log_bin_trust_routine_creators;
-
-
---echo '#---------------------FN_DYNVARS_064_08----------------------#'
-###################################################################
-#   Check if variable can be accessed with and without @@ sign    #
-###################################################################
-
-SET @@global.log_bin_trust_routine_creators = TRUE;
-SELECT @@log_bin_trust_routine_creators;
---Error ER_UNKNOWN_TABLE
-SELECT local.log_bin_trust_routine_creators;
---Error ER_UNKNOWN_TABLE
-SELECT session.log_bin_trust_routine_creators;
---Error ER_BAD_FIELD_ERROR
-SELECT log_bin_trust_routine_creators = @@session.log_bin_trust_routine_creators;
-
-
-####################################
-#     Restore initial value        #
-####################################
-
-SET @@global.log_bin_trust_routine_creators = @start_global_value;
-SELECT @@global.log_bin_trust_routine_creators;
-
-
-###################################################################
-#                 END OF log_bin_trust_routine_creators TESTS     #
-###################################################################
-

=== modified file 'mysql-test/t/union.test'
--- a/mysql-test/t/union.test	2008-09-10 10:40:14 +0000
+++ b/mysql-test/t/union.test	2008-09-10 12:50:02 +0000
@@ -93,64 +93,6 @@ SELECT @a:=1 UNION SELECT @a:=@a+1;
 
 
 #
-# Bug#32858: Erro: "Incorrect usage of UNION and INTO" does not take subselects 
-# into account
-#
-CREATE TABLE t1 (a INT);
-INSERT INTO t1 VALUES (1);
-
-SELECT a INTO @v FROM (
-  SELECT a FROM t1
-  UNION
-  SELECT a FROM t1
-) alias;
-
-SELECT a INTO OUTFILE 'union.out.file' FROM (
-  SELECT a FROM t1
-  UNION
-  SELECT a FROM t1 WHERE 0
-) alias;
-
-SELECT a INTO DUMPFILE 'union.out.file2' FROM (
-  SELECT a FROM t1
-  UNION
-  SELECT a FROM t1 WHERE 0
-) alias;
-
-#
-# INTO will not be allowed in subqueries in version 5.1 and above.
-#
-SELECT a FROM (
-  SELECT a FROM t1
-  UNION
-  SELECT a INTO @v FROM t1
-) alias;
-
-SELECT a FROM (
-  SELECT a FROM t1
-  UNION
-  SELECT a INTO OUTFILE 'union.out.file3' FROM t1
-) alias;
-
-SELECT a FROM (
-  SELECT a FROM t1
-  UNION
-  SELECT a INTO DUMPFILE 'union.out.file4' FROM t1
-) alias;
-
-SELECT a FROM t1 UNION SELECT a INTO @v FROM t1;
-SELECT a FROM t1 UNION SELECT a INTO OUTFILE 'union.out.file5' FROM t1;
-SELECT a FROM t1 UNION SELECT a INTO OUTFILE 'union.out.file6' FROM t1;
---error ER_WRONG_USAGE
-SELECT a INTO @v FROM t1 UNION SELECT a FROM t1;
---error ER_WRONG_USAGE
-SELECT a INTO OUTFILE 'union.out.file7' FROM t1 UNION SELECT a FROM t1;
---error ER_WRONG_USAGE
-SELECT a INTO DUMPFILE 'union.out.file8' FROM t1 UNION SELECT a FROM t1;
-
-DROP TABLE t1;
-
-#
 # Test bug reported by joc@presence-pc.com
 #
 

=== modified file 'sql/backup/backup_aux.h'
--- a/sql/backup/backup_aux.h	2008-07-31 10:45:02 +0000
+++ b/sql/backup/backup_aux.h	2008-08-21 19:28:49 +0000
@@ -47,6 +47,12 @@ storage_engine_ref get_se_by_name(const 
 namespace backup {
 
 /**
+  Constants for appending uniqueness to privileges in backup catalog.
+*/
+#define UNIQUE_PRIV_KEY_LEN 9
+#define UNIQUE_PRIV_KEY_FORMAT "%08lu"
+
+/**
   Local version of LEX_STRING structure.
 
   Defines various constructors for convenience.

=== modified file 'sql/backup/backup_info.cc'
--- a/sql/backup/backup_info.cc	2008-08-05 08:04:30 +0000
+++ b/sql/backup/backup_info.cc	2008-08-20 13:23:10 +0000
@@ -309,7 +309,7 @@ Backup_info::Dep_node::get_key(const uch
 Backup_info::Backup_info(Backup_restore_ctx &ctx)
   :m_ctx(ctx), m_state(Backup_info::ERROR), native_snapshots(8),
    m_dep_list(NULL), m_dep_end(NULL), 
-   m_srout_end(NULL), m_view_end(NULL), m_trigger_end(NULL)
+   m_srout_end(NULL), m_view_end(NULL), m_trigger_end(NULL), m_event_end(NULL)
 {
   using namespace backup;
 
@@ -786,6 +786,18 @@ int Backup_info::add_db_items(Db &db)
   if (add_objects(db, BSTREAM_IT_TRIGGER, *it))
     goto error;
   
+  delete it;
+  it= get_all_db_grants(m_ctx.m_thd, &db.name());
+
+  if (!it)
+  {
+    m_ctx.fatal_error(ER_BACKUP_LIST_DB_PRIV, db.name().ptr());
+    goto error;
+  }
+
+  if (add_objects(db, BSTREAM_IT_PRIVILEGE, *it))
+    goto error;
+
   goto finish;
 
  error:
@@ -1002,7 +1014,7 @@ Backup_info::add_db_object(Db &db, const
   ulong pos= db.obj_count();
 
   DBUG_ASSERT(obj);
-  const ::String *name= obj->get_name();
+  String *name= (String *)obj->get_name();
   DBUG_ASSERT(name);
 
   switch (type) {
@@ -1016,12 +1028,29 @@ Backup_info::add_db_object(Db &db, const
   case BSTREAM_IT_SFUNC:  error= ER_BACKUP_CATALOG_ADD_SROUT; break;
   case BSTREAM_IT_EVENT:  error= ER_BACKUP_CATALOG_ADD_EVENT; break;
   case BSTREAM_IT_TRIGGER: error= ER_BACKUP_CATALOG_ADD_TRIGGER; break;
+  case BSTREAM_IT_PRIVILEGE: error= ER_BACKUP_CATALOG_ADD_PRIV; break;
   
   // Only known types of objects should be added to the catalogue.
   default: DBUG_ASSERT(FALSE);
 
   }
 
+  /*
+    Generate a unique name for the privilege (grant) objects.
+    Note: this name does not alter the mechanics of the
+          grant objects in si_objects.cc
+  */
+  if (type == BSTREAM_IT_PRIVILEGE)
+  {
+    String new_name;
+    char buff[10];
+    sprintf(buff, UNIQUE_PRIV_KEY_FORMAT, pos);
+    new_name.append(*name);
+    new_name.append(" ");
+    new_name.append(buff);
+    name->copy(new_name);
+  }
+
   /* 
     Add new object to the dependency list. If it is a view, add its
     dependencies first.
@@ -1068,9 +1097,8 @@ Backup_info::add_db_object(Db &db, const
     objects.
    */
 
-  // Add object to catalogue
   Dbobj *o= Image_info::add_db_object(db, type, *name, pos);
-  
+ 
   if (!o)
   {
     m_ctx.fatal_error(error, db.name().ptr(), name->ptr());
@@ -1199,6 +1227,12 @@ int Backup_info::add_to_dep_list(const o
   break;
   
   case BSTREAM_IT_EVENT: 
+    end= &m_event_end;
+    if (!m_event_end)
+      m_event_end= m_trigger_end ? m_trigger_end : m_view_end ? m_view_end : m_srout_end;
+  break;
+
+  case BSTREAM_IT_PRIVILEGE:
     end= &m_dep_end;
   break;
    

=== modified file 'sql/backup/backup_info.h'
--- a/sql/backup/backup_info.h	2008-05-17 15:54:19 +0000
+++ b/sql/backup/backup_info.h	2008-08-20 13:23:10 +0000
@@ -141,6 +141,12 @@ class Backup_info: public backup::Image_
    */
   Dep_node  *m_trigger_end;
   
+  /** 
+    Points at the last event on the dependency list. NULL if events section
+    is empty.
+   */
+  Dep_node  *m_event_end;
+  
   /**
     Hash keeping all elements stored in the dependency list.
 

=== modified file 'sql/backup/backup_test.cc'
--- a/sql/backup/backup_test.cc	2008-07-19 03:03:39 +0000
+++ b/sql/backup/backup_test.cc	2008-08-20 13:23:10 +0000
@@ -44,14 +44,20 @@ int execute_backup_test_command(THD *thd
   field_list.push_back(new Item_empty_string("serialization", 13));
   protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
 
-  obs::ObjIterator *it= obs::get_databases(thd);
-
-  if (it)
+  //obs::ObjIterator *it= obs::get_databases(thd);
+  List_iterator<LEX_STRING> it(*db_list);
+  
+  //if (it)
   {
     obs::Obj *db;
 
-    while ((db= it->next()))
+    //while ((db= it->next()))
+    LEX_STRING *dbname;
+    while ((dbname= it++))
     {
+      String dir;
+      dir.copy(dbname->str, dbname->length, system_charset_info);
+      db= get_database(&dir);
 
       if (is_internal_db_name(db->get_db_name()))
           continue;
@@ -223,18 +229,42 @@ int execute_backup_test_command(THD *thd
 
           delete event;
         }
-
-        delete tit;
       }
 
-      // That's it.
+      //
+      // List db grants.
+      //
+      tit= obs::get_all_db_grants(thd, db->get_name());
 
-      delete db;
-    }
-  }
+      if (tit)
+      {
+        obs::Obj *grant;
+
+        while ((grant= tit->next()))
+        {
+          String serial;
+          serial.length(0);
+          protocol->prepare_for_resend();
+          protocol->store(const_cast<String*>(db->get_name()));
+          protocol->store(const_cast<String*>(grant->get_name()));
+          String user;
+          String host;
+          String *user_host= (String *)grant->get_name();
+          user_exists(thd, user_host);
+          protocol->store(C_STRING_WITH_LEN("GRANT"),
+                          system_charset_info);
+          grant->serialize(thd, &serial);
+          protocol->store(&serial);
+          protocol->write();
 
-  delete it;
+          delete grant;
+        }
 
+      delete tit;
+      }
+    }
+  }
+  thd->main_da.reset_diagnostics_area();
   my_eof(thd);
   DBUG_RETURN(res);
 }

=== modified file 'sql/backup/be_default.cc'
--- a/sql/backup/be_default.cc	2008-07-09 08:19:03 +0000
+++ b/sql/backup/be_default.cc	2008-08-18 08:25:56 +0000
@@ -381,6 +381,14 @@ result_t Backup::get_data(Buffer &buf)
     read_set=  cur_table->read_set;
     start_tbl_read(cur_table);
 
+    // The first time the table is accessed after opening it,
+    // cur_table->in_use points to the locking thread. It has to point
+    // to the backup thread before the table can be read
+    if (cur_table->in_use != locking_thd->m_thd) {
+      DBUG_ASSERT(cur_table->in_use == locking_thd->lock_thd);
+      cur_table->in_use= locking_thd->m_thd;
+    }
+
     buf.table_num= tbl_num;
     mode= READ_RCD;
   }

=== modified file 'sql/backup/image_info.cc'
--- a/sql/backup/image_info.cc	2008-07-31 10:45:02 +0000
+++ b/sql/backup/image_info.cc	2008-08-20 13:23:10 +0000
@@ -384,6 +384,7 @@ Image_info::Obj *find_obj(const Image_in
   case BSTREAM_IT_SFUNC:
   case BSTREAM_IT_EVENT:
   case BSTREAM_IT_TRIGGER:
+  case BSTREAM_IT_PRIVILEGE:
   {
     const st_bstream_dbitem_info &it=
                           reinterpret_cast<const st_bstream_dbitem_info&>(item);

=== modified file 'sql/backup/image_info.h'
--- a/sql/backup/image_info.h	2008-08-11 16:06:30 +0000
+++ b/sql/backup/image_info.h	2008-08-20 13:23:10 +0000
@@ -1012,6 +1012,17 @@ obs::Obj* Image_info::Dbobj::materialize
   case BSTREAM_IT_TRIGGER:   
     m_obj_ptr= obs::materialize_trigger(db_name, name, ver, &sdata);
     break;
+  case BSTREAM_IT_PRIVILEGE:
+  {
+    /*
+      Here we undo the uniqueness suffix for grants.
+    */
+    String new_name;
+    new_name.copy(*name);
+    new_name.length(new_name.length() - UNIQUE_PRIV_KEY_LEN);
+    m_obj_ptr= obs::materialize_db_grant(db_name, &new_name, ver, &sdata);
+    break;
+  }
   default: m_obj_ptr= NULL;
   }
 

=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc	2008-08-11 16:06:30 +0000
+++ b/sql/backup/kernel.cc	2008-08-21 11:36:09 +0000
@@ -905,6 +905,7 @@ int Backup_restore_ctx::do_backup()
   report_stats_pre(info);
 
   DBUG_PRINT("backup",("Writing preamble"));
+  DEBUG_SYNC(m_thd, "backup_before_write_preamble");
 
   if (write_preamble(info, s))
   {
@@ -1053,6 +1054,10 @@ int Backup_restore_ctx::do_restore()
 
   if (read_meta_data(info, s))
   {
+    // FIXME: detect errors.
+    // FIXME: error logging.
+    m_thd->main_da.reset_diagnostics_area();
+
     fatal_error(ER_BACKUP_READ_META);
     DBUG_RETURN(m_error);
   }
@@ -1427,6 +1432,7 @@ int bcat_add_item(st_bstream_image_heade
   case BSTREAM_IT_SFUNC:
   case BSTREAM_IT_EVENT:
   case BSTREAM_IT_TRIGGER:
+  case BSTREAM_IT_PRIVILEGE:
   {
     st_bstream_dbitem_info *it= (st_bstream_dbitem_info*)item;
     
@@ -1438,7 +1444,6 @@ int bcat_add_item(st_bstream_image_heade
     
     Image_info::Dbobj *it1= info->add_db_object(*db, item->type, name_str,
                                                 item->pos);
-  
     if (!it1)
       return BSTREAM_ERROR;
     
@@ -1689,6 +1694,7 @@ int bcat_create_item(st_bstream_image_he
   case BSTREAM_IT_EVENT:  create_err= ER_BACKUP_CANT_RESTORE_EVENT; break;
   case BSTREAM_IT_TRIGGER: create_err= ER_BACKUP_CANT_RESTORE_TRIGGER; break;
   case BSTREAM_IT_TABLESPACE: create_err= ER_BACKUP_CANT_RESTORE_TS; break;
+  case BSTREAM_IT_PRIVILEGE: create_err= ER_BACKUP_CANT_RESTORE_PRIV; break;
   
   /*
     TODO: Decide what to do when we come across unknown item:
@@ -1775,6 +1781,48 @@ int bcat_create_item(st_bstream_image_he
 
   // Create the object.
 
+  /*
+    We need to check to see if the user exists (grantee) and if not, 
+    do not execute the grant. 
+  */
+  if (item->type == BSTREAM_IT_PRIVILEGE)
+  {
+    /*
+      Issue warning to the user that grant was skipped. 
+
+      @todo Replace write_message() call with the result of the revised
+            error handling work in WL#4384 with possible implementation
+            via a related bug report.
+    */
+    if (!obs::user_exists(thd, sobj->get_name()))
+    {
+      info->m_ctx.write_message(log_level::WARNING, 
+                                ER(ER_BACKUP_GRANT_SKIPPED),
+                                create_stmt);
+      return BSTREAM_OK; 
+    }
+    /*
+      We need to check the grant against the database list to ensure the
+      grants have not been altered to apply to another database.
+    */
+    ::String db_name;  // db name extracted from grant statement
+    char *start;
+    char *end;
+    int size= 0;
+
+    start= strstr((char *)create_stmt.begin, "ON ") + 3;
+    end= strstr(start, ".");
+    size= end - start;
+    db_name.alloc(size);
+    db_name.length(0);
+    db_name.append(start, size);
+    if (!info->has_db(db_name))
+    {
+      info->m_ctx.fatal_error(ER_BACKUP_GRANT_WRONG_DB, create_stmt);
+      return BSTREAM_ERROR;
+    }
+  }
+
   if (sobj->execute(thd))
   {
     info->m_ctx.fatal_error(create_err, desc);
@@ -1820,6 +1868,7 @@ int bcat_get_item_create_query(st_bstrea
   case BSTREAM_IT_EVENT:  meta_err= ER_BACKUP_GET_META_EVENT; break;
   case BSTREAM_IT_TRIGGER: meta_err= ER_BACKUP_GET_META_TRIGGER; break;
   case BSTREAM_IT_TABLESPACE: meta_err= ER_BACKUP_GET_META_TS; break;
+  case BSTREAM_IT_PRIVILEGE: meta_err= ER_BACKUP_GET_META_PRIV; break;
   
   /*
     This can't happen - the item was obtained from the backup kernel.

=== modified file 'sql/ddl_blocker.cc'
--- a/sql/ddl_blocker.cc	2008-06-25 13:39:04 +0000
+++ b/sql/ddl_blocker.cc	2008-08-19 15:35:29 +0000
@@ -101,29 +101,49 @@ void DDL_blocker_class::end_DDL()
 /**
     check_DDL_blocker
 
-    Check to see if we are blocked from continuing. If so,
-    wait until the blocked process signals the condition.
+    Check to see if we are blocked from continuing. If so, wait until block is 
+    removed or the timeout specified by backup_wait_timeout variable occurs.
+    
+    @param[in] thd        The THD object from the caller.
 
-    @param thd The THD object from the caller.
-    @returns TRUE
+    @note: This operation blocks DDL operations until end_ddl() is called.
+
+    @returns TRUE if not blocked
+    @returns FALSE if ddl is blocked and timeout occurs
   */
 my_bool DDL_blocker_class::check_DDL_blocker(THD *thd)
 {
+  int ret = 0;
+  struct timespec ddl_timeout;
   DBUG_ENTER("check_DDL_blocker()");
   DEBUG_SYNC(thd, "before_check_ddl_blocked");
 
+  set_timespec(ddl_timeout, thd->backup_wait_timeout);
+
   /*
     Check the ddl blocker condition. Rest until ddl blocker is released.
   */
   pthread_mutex_lock(&THR_LOCK_DDL_is_blocked);
   thd->enter_cond(&COND_DDL_blocker, &THR_LOCK_DDL_is_blocked,
                   "DDL blocker: DDL is blocked");
-  while (DDL_blocked && !thd->DDL_exception)
-    pthread_cond_wait(&COND_DDL_blocker, &THR_LOCK_DDL_is_blocked);
-  start_DDL();
-  thd->exit_cond("DDL blocker: Ok to run DDL");
-  DEBUG_SYNC(thd, "after_start_ddl");
-  DBUG_RETURN(TRUE);
+  while (DDL_blocked && !thd->DDL_exception && (ret == 0))
+  {
+    if (thd->backup_wait_timeout == 0)
+      ret = -1;
+    else
+      ret= pthread_cond_timedwait(&COND_DDL_blocker, &THR_LOCK_DDL_is_blocked,
+                                  &ddl_timeout);
+  }
+  thd->exit_cond("DDL blocker: DDL is not blocked");
+  if (ret == 0)
+  {
+    start_DDL();
+    DEBUG_SYNC(thd, "after_start_ddl");
+  }
+  else
+    my_error(ER_DDL_TIMEOUT, MYF(0), thd->query);
+
+  DBUG_RETURN(ret == 0);
 }
 
 /**

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2008-08-27 16:48:24 +0000
+++ b/sql/mysql_priv.h	2008-09-04 13:46:04 +0000
@@ -638,6 +638,8 @@ extern void debug_sync(THD *thd, const c
 #define DEBUG_SYNC(_thd_, _sync_point_name_)    /* disabled DEBUG_SYNC */
 #endif /* defined(ENABLED_DEBUG_SYNC) */
 
+#define BACKUP_WAIT_TIMEOUT_DEFAULT 50;
+
 /* BINLOG_DUMP options */
 
 #define BINLOG_DUMP_NON_BLOCK   1

=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc	2008-09-09 12:48:29 +0000
+++ b/sql/set_var.cc	2008-09-10 12:50:02 +0000
@@ -230,6 +230,7 @@ static sys_var_long_ptr	sys_concurrent_i
 static sys_var_long_ptr	sys_connect_timeout(&vars, "connect_timeout",
 					    &connect_timeout);
 static sys_var_const_str       sys_datadir(&vars, "datadir", mysql_real_data_home);
+static sys_var_backup_wait_timeout sys_backup_wait_timeout(&vars, "backup_wait_timeout");
 #ifndef DBUG_OFF
 static sys_var_thd_dbug        sys_dbug(&vars, "debug");
 #endif
@@ -2851,6 +2852,61 @@ bool sys_var_insert_id::update(THD *thd,
 }
 
 
+/**
+  Get value.
+
+  Returns the value for the backup_wait_timeout session variable.
+
+  @param[IN] thd    Thread object
+  @param[IN] type   Type of variable
+  @param[IN] base   Not used 
+
+  @returns value of variable
+*/
+uchar *sys_var_backup_wait_timeout::value_ptr(THD *thd, enum_var_type type,
+				   LEX_STRING *base)
+{
+  thd->sys_var_tmp.ulong_value= thd->backup_wait_timeout;
+  return (uchar*) &thd->sys_var_tmp.ulonglong_value;
+}
+
+
+/**
+  Update value.
+
+  Set the backup_wait_timeout variable.
+
+  @param[IN] thd    Thread object
+  @param[IN] var    Pointer to value from command.
+
+  @returns 0
+*/
+bool sys_var_backup_wait_timeout::update(THD *thd, set_var *var)
+{
+  if (var->save_result.ulong_value > (LONG_MAX/1000))
+    thd->backup_wait_timeout= LONG_MAX/1000;
+  else
+    thd->backup_wait_timeout= var->save_result.ulong_value;
+  return 0;
+}
+
+
+/**
+  Set default value.
+
+  Set the backup_wait_timeout variable to the default value.
+
+  @param[IN] thd    Thread object
+  @param[IN] type   Type of variable
+
+  @returns 0
+*/
+void sys_var_backup_wait_timeout::set_default(THD *thd, enum_var_type type)
+{ 
+  thd->backup_wait_timeout= BACKUP_WAIT_TIMEOUT_DEFAULT; 
+}
+
+
 uchar *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type,
 				   LEX_STRING *base)
 {

=== modified file 'sql/set_var.h'
--- a/sql/set_var.h	2008-09-09 12:48:29 +0000
+++ b/sql/set_var.h	2008-09-10 12:50:02 +0000
@@ -655,6 +655,31 @@ public:
 };
 
 
+/**
+  Backup_wait_timeout system variable class.
+
+  This class consolidates the mechanism to manage the backup_wait_timeout
+  system variable. It is a session only variable thus we check the type for
+  check_type() and check_default() to ensure it isn't accessed as a global.
+
+  A set_default() method is provided to allow the SET command :
+  SET backup_wait_TIMEOUT = DEFAULT; 
+*/
+class sys_var_backup_wait_timeout :public sys_var
+{
+public:
+  sys_var_backup_wait_timeout(sys_var_chain *chain, const char *name_arg)
+    :sys_var(name_arg)
+  { chain_sys_var(chain); }
+  bool update(THD *thd, set_var *var);
+  bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
+  bool check_default(enum_var_type type) { return type == OPT_GLOBAL; }
+  SHOW_TYPE show_type() { return SHOW_LONG; }
+  uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
+  void set_default(THD *thd, enum_var_type type);
+};
+
+
 class sys_var_insert_id :public sys_var
 {
 public:

=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt	2008-08-22 13:21:31 +0000
+++ b/sql/share/errmsg.txt	2008-08-27 13:03:26 +0000
@@ -6275,7 +6275,7 @@ ER_BACKUP_CANT_RESTORE_DB
 ER_BACKUP_CANT_RESTORE_TABLE
 	eng "Could not restore table %-.64s"
 ER_BACKUP_CANT_RESTORE_VIEW
-	eng "Could not restore view %-.64s"
+	eng "Could not restore view %-.64s. Please check the view definition for possible missing dependencies."
 ER_BACKUP_CANT_RESTORE_SROUT
 	eng "Could not restore stored routine %-.64s"
 ER_BACKUP_CANT_RESTORE_EVENT
@@ -6374,3 +6374,17 @@ ER_BACKUP_RELEASE_NAME_LOCK_FAILED
   eng "Restore failed to release the name locks on the tables."
 ER_BACKUP_BACKUPDIR
   eng "The path specified for the system variable backupdir cannot be accessed or is invalid. ref: %-.64s"
+ER_DDL_TIMEOUT
+   eng "The backup wait timeout has expired for query '%-64s'."
+ER_BACKUP_LIST_DB_PRIV
+        eng "Can't enumerate grants in database '%-.64s'."
+ER_BACKUP_CATALOG_ADD_PRIV
+	eng "Failed to add grant '%-.64s' to the catalog"
+ER_BACKUP_GET_META_PRIV
+        eng "Failed to obtain meta-data for grant '%-.64s'."
+ER_BACKUP_CANT_RESTORE_PRIV
+        eng "Could not execute grant '%-.64s'."
+ER_BACKUP_GRANT_SKIPPED
+        eng "The grant '%-.64s' was skipped because the user does not exist."
+ER_BACKUP_GRANT_WRONG_DB
+        eng "The grant '%-.64s' failed. Database not included in the backup image."

=== modified file 'sql/si_objects.cc'
--- a/sql/si_objects.cc	2008-08-11 10:41:41 +0000
+++ b/sql/si_objects.cc	2008-08-21 11:36:09 +0000
@@ -759,6 +759,123 @@ private:
   String m_create_stmt;
 };
 
+/**
+   @class DbGrantObj
+
+   This class provides an abstraction to database-level grants.
+   This class will permit the recording and replaying of these
+   grants.
+*/
+class DbGrantObj : public Obj
+{
+public:
+  DbGrantObj(const String *grantee,
+             const String *db_name,
+             const String *priv_type);
+
+public:
+  virtual bool materialize(uint serialization_version,
+                           const String *serialization);
+
+  const String* get_name()
+  {
+    return &m_name;
+  }
+
+  const String *get_db_name()
+  {
+    return &m_db_name;
+  }
+
+  const String *get_priv_type()
+  {
+    return &m_priv_type;
+  }
+
+protected:
+  // These attributes are to be used only for serialization.
+  String m_db_name;   ///< corresponds with TABLE_SCHEMA in IS tables.
+  String m_name;      ///< name used to list in catalog.
+  String m_grantee;   ///< corresponds with GRANTEE in IS tables.
+  String m_priv_type; ///< corresponds with PRIVILEGE_TYPE in IS tables.
+
+  bool drop(THD *thd) { return 0; };  // Drop not supported.
+  virtual bool do_execute(THD *thd);
+
+private:
+  virtual bool do_serialize(THD *thd, String *serialization);
+  // These attributes are to be used only for materialization.
+  String m_grant_stmt;
+};
+
+/**
+   @class TblGrantObj
+
+   This class provides an abstraction to table-level and routine-level grants.
+   This class will permit the recording and replaying of these
+   grants.
+*/
+class TblGrantObj : public DbGrantObj
+{
+public:
+  TblGrantObj(const String *grantee,
+              const String *db_name,
+              const String *table_name,
+              const String *priv_type);
+
+public:
+
+  const String *get_table_name()
+  {
+    return &m_table_name;
+  }
+
+protected:
+  // These attributes are to be used only for serialization.
+  String m_table_name; ///< corresponds with TABLE_NAME in IS tables.
+
+
+private:
+  virtual bool do_serialize(THD *thd, String *serialization);
+
+  // These attributes are to be used only for materialization.
+  String m_grant_stmt;
+};
+
+/**
+   @class ColGrantObj
+
+   This class provides an abstraction to column-level grants.
+   This class will permit the recording and replaying of these
+   grants.
+*/
+class ColGrantObj : public TblGrantObj
+{
+public:
+  ColGrantObj(const String *grantee,
+              const String *db_name,
+              const String *table_name,
+              const String *col_name,
+              const String *priv_type);
+
+public:
+
+  const String *get_col_name()
+  {
+    return &m_col_name;
+  }
+
+protected:
+  // These attributes are to be used only for serialization.
+  String m_col_name; ///< corresponds with COLUMN_NAME in IS tables.
+
+private:
+  virtual bool do_serialize(THD *thd, String *serialization);
+
+  // These attributes are to be used only for materialization.
+  String m_grant_stmt;
+};
+
 ///////////////////////////////////////////////////////////////////////////
 
 //
@@ -797,9 +914,9 @@ public:
 
 protected:
   virtual Obj *create_obj(TABLE *t) = 0;
+  THD *m_thd;
 
 private:
-  THD *m_thd;
   TABLE *m_is_table;
   handler *m_ha;
   my_bitmap_map *m_orig_columns;
@@ -938,6 +1055,67 @@ private:
   String m_db_name;
 };
 
+class DbGrantIterator : public InformationSchemaIterator
+{
+public:
+  DbGrantIterator(THD *thd,
+                 const String *db_name,
+                 TABLE *is_table,
+                 handler *ha,
+                 my_bitmap_map *orig_columns) :
+    InformationSchemaIterator(thd, is_table, ha, orig_columns)
+  {
+    m_db_name.copy(*db_name);
+  }
+
+protected:
+  virtual DbGrantObj *create_obj(TABLE *t);
+
+private:
+  String m_db_name;
+};
+ 
+class TblGrantIterator : public InformationSchemaIterator
+{
+public:
+  TblGrantIterator(THD *thd,
+                  const String *db_name,
+                  TABLE *is_table,
+                  handler *ha,
+                  my_bitmap_map *orig_columns) :
+    InformationSchemaIterator(thd, is_table, ha, orig_columns)
+  {
+    m_db_name.copy(*db_name);
+  }
+
+protected:
+  virtual TblGrantObj *create_obj(TABLE *t);
+
+private:
+  String m_db_name;
+};
+ 
+class ColGrantIterator : public InformationSchemaIterator
+{
+public:
+  ColGrantIterator(THD *thd,
+                  const String *db_name,
+                  TABLE *is_table,
+                  handler *ha,
+                  my_bitmap_map *orig_columns) :
+    InformationSchemaIterator(thd, is_table, ha, orig_columns)
+  {
+    m_db_name.copy(*db_name);
+  }
+
+protected:
+  virtual ColGrantObj *create_obj(TABLE *t);
+
+private:
+  String m_db_name;
+};
+ 
+
 ///////////////////////////////////////////////////////////////////////////
 
 class DbStoredFuncIterator : public DbStoredProcIterator
@@ -1055,6 +1233,24 @@ bool InformationSchemaIterator::prepare_
       *is_table= open_schema_table(thd, st, NULL);
       break;
     }
+    case SCH_SCHEMA_PRIVILEGES:
+    {
+      st= find_schema_table(thd, "SCHEMA_PRIVILEGES");
+      *is_table= open_schema_table(thd, st, NULL);
+      break;
+    }
+    case SCH_TABLE_PRIVILEGES:
+    {
+      st= find_schema_table(thd, "TABLE_PRIVILEGES");
+      *is_table= open_schema_table(thd, st, NULL);
+      break;
+    }
+    case SCH_COLUMN_PRIVILEGES:
+    {
+      st= find_schema_table(thd, "COLUMN_PRIVILEGES");
+      *is_table= open_schema_table(thd, st, NULL);
+      break;
+    }
     default:
     {
       st= get_schema_table(is_table_idx);
@@ -1320,6 +1516,141 @@ EventObj *DbEventIterator::create_obj(TA
   return new EventObj(&db_name, &event_name);
 }
 #endif
+
+///////////////////////////////////////////////////////////////////////////
+
+//
+// Implementation: DbGrantIterator class.
+//
+
+///////////////////////////////////////////////////////////////////////////
+
+DbGrantObj* DbGrantIterator::create_obj(TABLE *t)
+{
+  String grantee;   // corresponds with GRANTEE
+  String db_name;   // corresponds with TABLE_SCHEMA
+  String priv_type; // corresponds with PRIVILEGE_TYPE
+
+  t->field[0]->val_str(&grantee);
+  t->field[2]->val_str(&db_name);
+  t->field[3]->val_str(&priv_type);
+
+  /*
+    The fill method for SCHEMA_PRIVILEGES does not use the COND portion
+    of the generic fill() method. Thus, we have to do the restriction here.
+
+    Ensure the only rows sent back from iterator are the ones that match the
+    database specified.
+  */
+  if (db_name == m_db_name)
+  {
+    DBUG_PRINT("DbGrantIterator::create", (" Found grant %s %s %s", 
+     db_name.ptr(), grantee.ptr(), priv_type.ptr()));
+
+    /*
+      Include grants for only users that exist at time of backup.
+    */
+    if (user_exists(m_thd, &grantee))
+      return new DbGrantObj(&grantee, &db_name, &priv_type);
+    else
+      return NULL;
+  }
+  else
+    return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+//
+// Implementation: TblGrantIterator class.
+//
+
+///////////////////////////////////////////////////////////////////////////
+
+TblGrantObj* TblGrantIterator::create_obj(TABLE *t)
+{
+  String grantee;   // corresponds with GRANTEE
+  String db_name;   // corresponds with TABLE_SCHEMA
+  String tbl_name;  // corresponds with TABLE_NAME
+  String priv_type; // corresponds with PRIVILEGE_TYPE
+ 
+  t->field[0]->val_str(&grantee);
+  t->field[2]->val_str(&db_name);
+  t->field[3]->val_str(&tbl_name);
+  t->field[4]->val_str(&priv_type);
+
+  /*
+    The fill method for TABLE_PRIVILEGES does not use the COND portion
+    of the generic fill() method. Thus, we have to do the restriction here.
+
+    Ensure the only rows sent back from iterator are the ones that match the
+    database specified.
+  */
+  if (db_name == m_db_name)
+  {
+    DBUG_PRINT("TblGrantIterator::create", (" Found grant %s %s %s %s", 
+     db_name.ptr(), grantee.ptr(), tbl_name.ptr(), priv_type.ptr()));
+
+    /*
+      Include grants for only users that exist at time of backup.
+    */
+    if (user_exists(m_thd, &grantee))
+      return new TblGrantObj(&grantee, &db_name, &tbl_name, &priv_type);
+    else
+      return NULL;
+  }
+  else
+    return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+//
+// Implementation: ColGrantIterator class.
+//
+
+///////////////////////////////////////////////////////////////////////////
+
+ColGrantObj* ColGrantIterator::create_obj(TABLE *t)
+{
+  String grantee;   // corresponds with GRANTEE
+  String db_name;   // corresponds with TABLE_SCHEMA
+  String tbl_name;  // corresponds with TABLE_NAME
+  String col_name;  // corresponds with COLUMN_NAME
+  String priv_type; // corresponds with PRIVILEGE_TYPE
+ 
+  t->field[0]->val_str(&grantee);
+  t->field[2]->val_str(&db_name);
+  t->field[3]->val_str(&tbl_name);
+  t->field[4]->val_str(&col_name);
+  t->field[5]->val_str(&priv_type);
+
+  /*
+    The fill method for COLUMN_PRIVILEGES does not use the COND portion
+    of the generic fill() method. Thus, we have to do the restriction here.
+
+    Ensure the only rows sent back from iterator are the ones that match the
+    database specified.
+  */
+  if (db_name == m_db_name)
+  {
+    DBUG_PRINT("ColGrantIterator::create", (" Found grant %s %s %s %s %s", 
+     db_name.ptr(), grantee.ptr(), tbl_name.ptr(), col_name.ptr(),
+     priv_type.ptr()));
+
+    /*
+      Include grants for only users that exist at time of backup.
+    */
+    if (user_exists(m_thd, &grantee))
+      return new ColGrantObj(&grantee, &db_name, &tbl_name,
+                             &col_name, &priv_type);
+    else
+      return NULL;
+  }
+  else
+    return NULL;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 
 //
@@ -1502,6 +1833,18 @@ DbEventIterator *
 create_is_iterator<DbEventIterator>(THD *, enum_schema_tables, const String *);
 #endif
 
+template
+DbGrantIterator *
+create_is_iterator<DbGrantIterator>(THD *, enum_schema_tables, const String *);
+
+template
+TblGrantIterator *
+create_is_iterator<TblGrantIterator>(THD *, enum_schema_tables, const String *);
+
+template
+ColGrantIterator *
+create_is_iterator<ColGrantIterator>(THD *, enum_schema_tables, const String *);
+
 ObjIterator *get_db_tables(THD *thd, const String *db_name)
 {
   return create_is_iterator<DbTablesIterator>(thd, SCH_TABLES, db_name);
@@ -1536,6 +1879,56 @@ ObjIterator *get_db_events(THD *thd, con
 #endif
 }
 
+/**
+  GrantObjIterator constructor
+
+  This constructor initializes iterators for the grants supported.
+  These include database-, table- and routine-, and column-level grants.
+  The iterators return all of the grants for the database specified.
+*/
+GrantObjIterator::GrantObjIterator(THD *thd, const String *db_name)
+: ObjIterator()
+{
+  db_grants= create_is_iterator<DbGrantIterator>(thd, 
+                                                 SCH_SCHEMA_PRIVILEGES, 
+                                                 db_name);
+  tbl_grants= create_is_iterator<TblGrantIterator>(thd,
+                                                 SCH_TABLE_PRIVILEGES, 
+                                                 db_name);
+  col_grants= create_is_iterator<ColGrantIterator>(thd, 
+                                                 SCH_COLUMN_PRIVILEGES, 
+                                                 db_name);
+}
+
+Obj *GrantObjIterator::next()
+{
+  Obj *obj= 0;
+  obj= db_grants->next();
+  if (!obj)
+    obj= tbl_grants->next();
+  if (!obj)
+    obj= col_grants->next();
+  return obj;
+}
+
+/**
+  Creates a high-level iterator that iterates over database-, table-,
+  routine-, and column-level privileges which shall permit a single
+  iterator from the si_objects to retrieve all of the privileges for 
+  a given database.
+
+  @param[IN] thd      Current THD object
+  @param[IN] db_name  Name of database to get grants
+
+  @Note The client is responsible for destroying the returned iterator.
+
+  @return a pointer to an iterator object.
+    @retval NULL in case of error.
+*/
+ObjIterator *get_all_db_grants(THD *thd, const String *db_name)
+{
+  return new GrantObjIterator(thd, db_name);
+}
 
 ///////////////////////////////////////////////////////////////////////////
 
@@ -1607,7 +2000,7 @@ bool DatabaseObj::do_serialize(THD *thd,
   if (check_db_dir_existence(m_db_name.c_ptr()))
   {
     my_error(ER_BAD_DB_ERROR, MYF(0), m_db_name.c_ptr());
-    DBUG_RETURN(FALSE);
+    DBUG_RETURN(TRUE);
   }
 
   load_db_opt_by_name(thd, m_db_name.c_ptr(), &create);
@@ -1941,8 +2334,9 @@ bool TriggerObj::do_serialize(THD *thd, 
 
   alloc_mdl_locks(lst, thd->mem_root);
 
+  DBUG_EXECUTE_IF("backup_fail_add_trigger", DBUG_RETURN(TRUE););
   if (open_tables(thd, &lst, &num_tables, 0))
-    DBUG_RETURN(FALSE);
+    DBUG_RETURN(TRUE);
 
   DBUG_ASSERT(num_tables == 1);
   Table_triggers_list *triggers= lst->table->triggers;
@@ -2584,6 +2978,191 @@ bool TablespaceObj::do_execute(THD *thd)
 }
 
 ///////////////////////////////////////////////////////////////////////////
+//
+// Implementation: DbGrantObj class.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+DbGrantObj::DbGrantObj(const String *grantee,
+                       const String *db_name,
+                       const String *priv_type)
+{
+  // copy strings to newly allocated memory
+  m_db_name.copy(*db_name);
+  m_grantee.copy(*grantee);
+  m_name.copy(*grantee);
+  m_priv_type.copy(*priv_type);
+}
+
+/**
+  Serialize the object.
+
+  This method produces the data necessary for materializing the object
+  on restore (creates object).
+
+  @param[in]  thd            Thread context.
+  @param[out] serialization  The data needed to recreate this object.
+
+  @note this method will return an error if the db_name is either
+        mysql or information_schema as these are not objects that
+        should be recreated using this interface.
+
+  @returns Error status.
+    @retval FALSE on success
+    @retval TRUE on error
+*/
+bool DbGrantObj::do_serialize(THD *thd, String *serialization)
+{
+  DBUG_ENTER("DbGrantObj::do_serialize()");
+  serialization->length(0);
+  serialization->append("GRANT ");
+  serialization->append(m_priv_type);
+  serialization->append(" ON ");
+  serialization->append(m_db_name);
+  serialization->append(".* TO ");
+  serialization->append(m_grantee);
+  DBUG_RETURN(0);
+}
+
+/**
+  Materialize the serialization string.
+
+  This method saves serialization string into a member variable.
+
+  @param[in]  serialization_version   version number of this interface
+  @param[in]  serialization           the string from serialize()
+
+  @todo take serialization_version into account
+
+  @returns Error status.
+    @retval FALSE on success
+    @retval TRUE on error
+*/
+bool DbGrantObj::materialize(uint serialization_version,
+                             const String *serialization)
+{
+  DBUG_ENTER("DbGrantObj::materialize()");
+  m_grant_stmt.copy(*serialization);
+  DBUG_RETURN(0);
+}
+
+/**
+  Create the object.
+
+  This method uses serialization string in a query and executes it.
+
+  @param[in]  thd  Thread context.
+
+  @returns Error status.
+    @retval FALSE on success
+    @retval TRUE on error
+*/
+bool DbGrantObj::do_execute(THD *thd)
+{
+  DBUG_ENTER("DbGrantObj::do_execute()");
+  DBUG_RETURN(execute_with_ctx(thd, &m_grant_stmt, true));
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Implementation: TblGrantObj class.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+TblGrantObj::TblGrantObj(const String *grantee,
+                         const String *db_name,
+                         const String *table_name,
+                         const String *priv_type) 
+: DbGrantObj(grantee, db_name, priv_type)
+{
+  // copy strings to newly allocated memory
+  m_table_name.copy(*table_name);
+}
+
+/**
+  Serialize the object.
+
+  This method produces the data necessary for materializing the object
+  on restore (creates object).
+
+  @param[in]  thd            Thread context.
+  @param[out] serialization  The data needed to recreate this object.
+
+  @note this method will return an error if the db_name is either
+        mysql or information_schema as these are not objects that
+        should be recreated using this interface.
+
+  @returns Error status.
+    @retval FALSE on success
+    @retval TRUE on error
+*/
+bool TblGrantObj::do_serialize(THD *thd, String *serialization)
+{
+  DBUG_ENTER("TblGrantObj::do_serialize()");
+  serialization->length(0);
+  serialization->append("GRANT ");
+  serialization->append(m_priv_type);
+  serialization->append(" ON ");
+  serialization->append(m_db_name);
+  serialization->append(".");
+  serialization->append(m_table_name);
+  serialization->append(" TO ");
+  serialization->append(m_grantee);
+  DBUG_RETURN(0);
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Implementation: ColGrantObj class.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+ColGrantObj::ColGrantObj(const String *grantee,
+                         const String *db_name,
+                         const String *table_name,
+                         const String *col_name,
+                         const String *priv_type) 
+: TblGrantObj(grantee, db_name, table_name, priv_type)
+{
+  // copy strings to newly allocated memory
+  m_col_name.copy(*col_name);
+}
+
+/**
+  Serialize the object.
+
+  This method produces the data necessary for materializing the object
+  on restore (creates object).
+
+  @param[in]  thd            Thread context.
+  @param[out] serialization  The data needed to recreate this object.
+
+  @note this method will return an error if the db_name is either
+        mysql or information_schema as these are not objects that
+        should be recreated using this interface.
+
+  @returns Error status.
+    @retval FALSE on success
+    @retval TRUE on error
+*/
+bool ColGrantObj::do_serialize(THD *thd, String *serialization)
+{
+  DBUG_ENTER("ColGrantObj::do_serialize()");
+  serialization->length(0);
+  serialization->append("GRANT ");
+  serialization->append(m_priv_type);
+  serialization->append("(");
+  serialization->append(m_col_name);
+  serialization->append(") ON ");
+  serialization->append(m_db_name);
+  serialization->append(".");
+  serialization->append(m_table_name);
+  serialization->append(" TO ");
+  serialization->append(m_grantee);
+  DBUG_RETURN(0);
+}
+
+///////////////////////////////////////////////////////////////////////////
 
 Obj *get_database(const String *db_name)
 {
@@ -2721,6 +3300,33 @@ Obj *materialize_tablespace(const String
   return obj;
 }
 
+Obj *get_db_grant(const String *grantee,
+                  const String *db_name)
+{
+  String priv_type;
+  priv_type.length(0);
+
+  return new DbGrantObj(grantee, db_name, &priv_type);
+}
+
+Obj *materialize_db_grant(const String *db_name,
+                          const String *grantee,
+                          uint serialization_version,
+                          const String *serialization)
+{
+  /*
+    Here we create a grant for the purposes of applying the
+    grants. We use DbGrantObj for all types of grants because
+    we only have the GRANT statement in the serialization
+    string and therefore do not that the 'parts' to create
+    the specific types. 
+  */
+  Obj *obj= get_db_grant(grantee, db_name);
+  obj->materialize(serialization_version, serialization);
+
+  return obj;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 
 bool is_internal_db_name(const String *db_name)
@@ -2744,6 +3350,90 @@ bool check_db_existence(const String *db
   return check_db_dir_existence(((String *) db_name)->c_ptr_safe());
 }
 
+/*
+  Splits grantee clause into user and host portions. Needed for checking
+  to see if user exists on system.
+*/
+int split_user_host(String *grantee, String *user, String *host)
+{
+  int len= 0;
+  int tics= 0;
+  char *ptr= 0;
+
+  /*
+    Since passwords are single byte characters and usernames can be multibyte
+    characters and the 0x40 = 64 = @ can occur in the username, we must search
+    for the first @ from the right.
+  */
+  len= grantee->length();
+  len--;
+  ptr= grantee->c_ptr() + len;
+  while ((len > 0) && (*ptr != '@'))
+  {
+    len--;
+    ptr= grantee->c_ptr() + len;
+  }
+
+  if (ptr == 0)
+    return -1;
+  len= ptr - grantee->c_ptr();
+  user->length(0);
+  char *cptr= grantee->c_ptr();
+
+  /*
+    String ' from strings.
+  */
+  if (strncmp(cptr, "'", 1) == 0)
+  {
+    cptr++;
+    len--;
+    tics++;
+  }
+  user->append(cptr, len - tics);
+  len= grantee->length() - len - 1 - tics;
+  host->length(0);
+
+  /*
+    String ' from strings.
+  */
+  cptr= ptr + 1;
+  tics= 0;
+  if (strncmp(cptr, "'", 1) == 0)
+  {
+    cptr++;
+    len--;
+  }
+  if (strncmp(cptr+len-1, "'", 1) == 0)
+    tics++;
+  host->append(cptr, len - tics);
+  return 0;
+}
+
+/*
+  Returns TRUE if user is defined on the system.
+*/
+bool user_exists(THD *thd, const String *grantee)
+{
+  String user;
+  String host;
+  bool user_exists= FALSE;
+
+  user.length(0);
+  host.length(0);
+  if (grantee)
+  {
+#ifndef EMBEDDED_LIBRARY
+    split_user_host((String *)grantee, &user, &host);
+    if (!user.ptr())
+      user.append("''");
+    user_exists= is_acl_user(host.ptr(), user.ptr());
+#else
+    user_exists= TRUE;
+#endif
+  }
+  return user_exists;
+}
+
 /**
   Locate the row in the information_schema view for this tablespace.
 

=== modified file 'sql/si_objects.h'
--- a/sql/si_objects.h	2008-07-05 08:41:26 +0000
+++ b/sql/si_objects.h	2008-08-20 13:23:10 +0000
@@ -115,6 +115,12 @@ private:
   friend Obj *materialize_tablespace(const String *,
                                      uint,
                                      const String *);
+
+  friend Obj *materialize_db_grant(const String *,
+                                   const String *,
+                                   uint,
+                                   const String *);
+
 };
 
 
@@ -222,6 +228,39 @@ public:
 
 };
 
+/**
+  GrantObjIternator is an encapsulation of the three iterators for each level
+  of grant supported: database-, table- and routine-, and column-level.
+*/
+class GrantObjIterator : public ObjIterator
+{
+public:
+  GrantObjIterator(THD *thd, const String *db_name);
+
+  ~GrantObjIterator() 
+  {
+    delete db_grants;
+    delete tbl_grants;
+    delete col_grants;
+  }
+
+  /**
+    This operation returns a pointer to the next object in an enumeration.
+    It returns NULL if there is no more objects.
+
+    The client is responsible to destroy the returned object.
+
+    @return a pointer to the object
+      @retval NULL if there is no more objects in an enumeration.
+  */
+  Obj *next();
+
+private:
+  ObjIterator *db_grants;  ///< database-level grants
+  ObjIterator *tbl_grants; ///< table- and routine-level grants
+  ObjIterator *col_grants; ///< column-level grants
+};
+
 ///////////////////////////////////////////////////////////////////////////
 
 // The functions in this section are intended to construct an instance of
@@ -429,6 +468,14 @@ ObjIterator *get_db_stored_functions(THD
 
 ObjIterator *get_db_events(THD *thd, const String *db_name);
 
+/*
+  Creates a high-level iterator that iterates over database-, table-,
+  routine-, and column-level privileges which shall permit a single
+  iterator from the si_objects to retrieve all of the privileges for 
+  a given database.
+*/
+ObjIterator *get_all_db_grants(THD *thd, const String *db_name);
+
 ///////////////////////////////////////////////////////////////////////////
 
 // The functions are intended to enumerate dependent objects.
@@ -506,6 +553,11 @@ Obj *materialize_tablespace(const String
                             uint serialization_version,
                             const String *serialialization);
 
+Obj *materialize_db_grant(const String *grantee,
+                          const String *db_name,
+                          uint serialization_version,
+                          const String *serialization);
+
 ///////////////////////////////////////////////////////////////////////////
 
 bool is_internal_db_name(const String *db_name);
@@ -522,6 +574,11 @@ bool is_internal_db_name(const String *d
 bool check_db_existence(const String *db_name);
 
 /*
+  Returns TRUE if user is defined on the system.
+*/
+bool user_exists(THD *thd, const String *grantee);
+
+/*
   This method returns a @c TablespaceObj object if the table has a tablespace.
 */
 Obj *get_tablespace_for_table(THD *thd, 

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2008-09-05 13:39:08 +0000
+++ b/sql/sql_class.cc	2008-09-10 12:50:02 +0000
@@ -537,6 +537,7 @@ THD::THD()
           when the DDL blocker is engaged.
   */
    DDL_exception(FALSE),
+   backup_wait_timeout(50),
 #if defined(ENABLED_DEBUG_SYNC)
    debug_sync_control(0),
 #endif /* defined(ENABLED_DEBUG_SYNC) */

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2008-09-05 13:39:08 +0000
+++ b/sql/sql_class.h	2008-09-10 12:50:02 +0000
@@ -1936,6 +1936,7 @@ public:
           when the DDL blocker is engaged.
   */
   my_bool DDL_exception; // Allow some DDL if there is an exception
+  ulong backup_wait_timeout;
 
   Locked_tables_list locked_tables_list;
 

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2008-09-10 10:40:14 +0000
+++ b/sql/sql_parse.cc	2008-09-10 12:50:02 +0000
@@ -2484,7 +2484,11 @@ mysql_execute_command(THD *thd)
       TABLE in the same way. That way we avoid that a new table is
       created during a gobal read lock.
     */
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+    {
+      res= 1;
+      goto ddl_blocker_err;
+    }
     if (!thd->locked_tables_mode &&
         !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
     {
@@ -2610,6 +2614,7 @@ mysql_execute_command(THD *thd)
     /* put tables back for PS rexecuting */
 end_with_restore_list:
     DDL_blocker->end_DDL();
+ddl_blocker_err:
     lex->link_first_table_back(create_table, link_to_local);
     break;
   }
@@ -2625,7 +2630,8 @@ end_with_restore_list:
     table without having to do a full rebuild.
   */
   {
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     /* Prepare stack copies to be re-execution safe */
     HA_CREATE_INFO create_info;
     Alter_info alter_info(lex->alter_info, thd->mem_root);
@@ -2693,7 +2699,8 @@ end_with_restore_list:
 
   case SQLCOM_ALTER_TABLE:
     {
-      DDL_blocker->check_DDL_blocker(thd);
+      if (!DDL_blocker->check_DDL_blocker(thd))
+        goto error;
       ulong priv=0;
       ulong priv_needed= ALTER_ACL;
 
@@ -2805,7 +2812,8 @@ end_with_restore_list:
         goto error;
     }
 
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     if (mysql_rename_tables(thd, first_table, 0))
     {
       DDL_blocker->end_DDL();
@@ -2905,7 +2913,8 @@ end_with_restore_list:
     if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, FALSE, FALSE, UINT_MAX))
       goto error; /* purecov: inspected */
     thd->enable_slow_log= opt_log_slow_admin_statements;
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     res= mysql_repair_table(thd, first_table, &lex->check_opt);
     DDL_blocker->end_DDL();
     /* ! we write after unlocking the table */
@@ -2957,7 +2966,8 @@ end_with_restore_list:
     if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, FALSE, FALSE, UINT_MAX))
       goto error; /* purecov: inspected */
     thd->enable_slow_log= opt_log_slow_admin_statements;
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
       mysql_recreate_table(thd, first_table) :
       mysql_optimize_table(thd, first_table, &lex->check_opt);
@@ -3198,7 +3208,8 @@ end_with_restore_list:
       goto error;
     }
 
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     res= mysql_truncate(thd, first_table, 0);
     DDL_blocker->end_DDL();
 
@@ -3301,7 +3312,8 @@ end_with_restore_list:
       /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
       thd->options|= OPTION_KEEP_LOG;
     }
-      DDL_blocker->check_DDL_blocker(thd);
+      if (!DDL_blocker->check_DDL_blocker(thd))
+        goto error;
     /* DDL and binlog write order protected by LOCK_open */
     res= mysql_rm_table(thd, first_table, lex->drop_if_exists,
 			lex->drop_temporary);
@@ -3547,7 +3559,8 @@ end_with_restore_list:
     if (check_access(thd,CREATE_ACL,lex->name.str, 0, 1, 0,
                      is_schema_db(lex->name.str)))
       break;
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias :
                               lex->name.str), &create_info, 0);
     DDL_blocker->end_DDL();
@@ -3585,7 +3598,8 @@ end_with_restore_list:
                  ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
       goto error;
     }
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     res= mysql_rm_db(thd, lex->name.str, lex->drop_if_exists, 0);
     DDL_blocker->end_DDL();
     break;
@@ -3623,7 +3637,8 @@ end_with_restore_list:
       goto error;
     }
 
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     res= mysql_upgrade_db(thd, db);
     DDL_blocker->end_DDL();
     if (!res)
@@ -3663,7 +3678,8 @@ end_with_restore_list:
                  ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
       goto error;
     }
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     res= mysql_alter_db(thd, db->str, &create_info);
     DDL_blocker->end_DDL();
     break;

Thread
bzr commit into mysql-6.0 branch (kgeorge:2828) Georgi Kodinov10 Sep