List:Commits« Previous MessageNext Message »
From:Chuck Bell Date:November 18 2009 5:30pm
Subject:bzr commit into mysql-6.0-backup branch (charles.bell:2889) Bug#47879
View as plain text  
#At file:///Users/cbell/source/bzr/mysql-6.0-bug-47879/ based on revid:charles.bell@stripped

 2889 Chuck Bell	2009-11-18 [merge]
      Local merge before push of BUG#47879.

    added:
      mysql-test/suite/backup/r/backup_restore_locking.result
      mysql-test/suite/backup/t/backup_restore_locking.test
    modified:
      client/mysqladmin.cc
      mysql-test/collections/default.experimental
      mysql-test/suite/backup/include/backup_ext.inc
      mysql-test/suite/backup/include/backup_xpfm_compat_backup.inc
      mysql-test/suite/backup/r/backup_errors.result
      mysql-test/suite/backup/r/backup_errors_compression.result
      mysql-test/suite/backup/r/backup_external.result
      mysql-test/suite/backup/r/backup_intr_errors.result
      mysql-test/suite/backup/r/backup_logs.result
      mysql-test/suite/backup/r/backup_logs_output.result
      mysql-test/suite/backup/r/backup_myisam.result
      mysql-test/suite/backup/r/backup_myisam_coverage.result
      mysql-test/suite/backup/r/backup_myisam_sync.result
      mysql-test/suite/backup/r/backup_no_engine.result
      mysql-test/suite/backup/t/backup_errors.test
      mysql-test/suite/backup/t/backup_external.test
      mysql-test/suite/backup/t/backup_external_non_win.test
      mysql-test/suite/backup/t/backup_external_non_win_not_falcon.test
      mysql-test/suite/backup/t/backup_logs.test
      mysql-test/suite/backup/t/backup_logs_output.test
      mysql-test/suite/backup/t/backup_myisam.test
      mysql-test/suite/backup/t/backup_myisam_coverage.test
      mysql-test/suite/backup/t/backup_myisam_sync.test
      mysql-test/suite/backup/t/backup_no_engine.test
      mysql-test/suite/backup_engines/r/backup_interruption.result
      sql/backup/backup_info.cc
      sql/backup/kernel.cc
      sql/backup/logger.h
      sql/backup/stream_v1_transport.c
      sql/log.cc
      sql/share/errmsg-utf8.txt
      sql/share/errmsg.txt
      sql/si_logs.cc
      sql/si_logs.h
      sql/si_objects.cc
      sql/si_objects.h
      sql/sql_base.cc
      sql/sql_delete.cc
      unittest/backup/bstr_callback_errors-t.c
      unittest/backup/bstr_eos-t.c
      unittest/backup/bstr_io_errors-t.c
      unittest/backup/bstr_random_chunks-t.c
=== modified file 'client/mysqladmin.cc'
--- a/client/mysqladmin.cc	2009-11-02 14:05:19 +0000
+++ b/client/mysqladmin.cc	2009-11-16 15:21:34 +0000
@@ -97,7 +97,8 @@ enum commands {
   ADMIN_FLUSH_HOSTS,      ADMIN_FLUSH_TABLES,    ADMIN_PASSWORD,
   ADMIN_PING,             ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS,
   ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE,     ADMIN_STOP_SLAVE,
-  ADMIN_FLUSH_THREADS,    ADMIN_OLD_PASSWORD,    ADMIN_FLUSH_BACKUP_LOGS
+  ADMIN_FLUSH_THREADS,    ADMIN_OLD_PASSWORD,    ADMIN_FLUSH_BACKUP_LOGS,
+  ADMIN_PURGE_BUP_LOGS,   ADMIN_PURGE_BUP_LOGS_ID, ADMIN_PURGE_BUP_LOGS_DATE
 };
 static const char *command_names[]= {
   "create",               "drop",                "shutdown",
@@ -108,6 +109,7 @@ static const char *command_names[]= {
   "ping",                 "extended-status",     "flush-status",
   "flush-privileges",     "start-slave",         "stop-slave",
   "flush-threads",        "old-password",        "flush-backup-logs",
+  "purge-backup-logs",    "purge-backup-logs-id", "purge-backup-logs-date",
   NullS
 };
 
@@ -895,6 +897,60 @@ static int execute_commands(MYSQL *mysql
       }
       break;
     }
+    /*
+      We have three forms of this command:
+      
+      PURGE BACKUP LOGS
+      PURGE BACKUP LOGS TO <id>
+      PURGE BACKUP LOGS BEFORE <date>
+    */
+    case ADMIN_PURGE_BUP_LOGS:
+    {
+      if (mysql_query(mysql,"purge backup logs"))
+      {
+        my_printf_error(0,"purge backup logs failed; error: '%s'", error_flags,
+                        mysql_error(mysql));
+        return -1;
+      }
+      break;
+    }
+    case ADMIN_PURGE_BUP_LOGS_ID:
+    {
+      char buff[FN_REFLEN+20];
+      if (argc < 2)
+      {
+	      my_printf_error(0, "Too few arguments to purge backup logs to", 
+                        error_flags);
+	      return 1;
+      }
+      sprintf(buff,"PURGE BACKUP LOGS TO %s", argv[1]);
+      if (mysql_query(mysql, buff))
+      {
+        my_printf_error(0,"purge backup logs failed; error: '%s'", error_flags,
+                        mysql_error(mysql));
+        return -1;
+      }
+      argc--; argv++;
+      break;
+    }
+    case ADMIN_PURGE_BUP_LOGS_DATE:
+    {
+      char buff[FN_REFLEN+20];
+      if (argc < 2)
+      {
+	      my_printf_error(0, "Too few arguments to purge backup logs before", 
+                        error_flags);
+      }
+      sprintf(buff,"PURGE BACKUP LOGS BEFORE '%s'", argv[1]);
+      if (mysql_query(mysql, buff))
+      {
+        my_printf_error(0,"purge backup logs failed; error: '%s'", error_flags,
+                        mysql_error(mysql));
+        return -1;
+      }
+      argc--; argv++;
+      break;
+    }
     case ADMIN_FLUSH_STATUS:
     {
       if (mysql_query(mysql,"flush status"))
@@ -1106,7 +1162,10 @@ static void usage(void)
   extended-status       Gives an extended status message from the server\n\
   flush-hosts           Flush all cached hosts\n\
   flush-logs            Flush all logs\n\
-  flush-backup-logs     Flush backup logs\n\
+  flush-backup-logs                   Flush backup logs\n\
+  purge-backup-logs                   Purge backup logs\n\
+  purge-backup-logs-id <backup_id>    Purge backup logs up to a given backup_id\n\
+  purge-backup-logs-date <datetime>   Purge backup logs before a given datetime\n\
   flush-status		Clear status variables\n\
   flush-tables          Flush all tables\n\
   flush-threads         Flush the thread cache\n\

=== modified file 'mysql-test/collections/default.experimental'
--- a/mysql-test/collections/default.experimental	2009-11-02 14:05:19 +0000
+++ b/mysql-test/collections/default.experimental	2009-11-13 12:10:39 +0000
@@ -3,8 +3,6 @@
 
 backup.backup_dbname_lctn2  @windows  @darwin   # Bug#46933 2009-08-26 alik backup_*_lctn2 tests fail on windows
 backup.backup_events                     # Bug#47211 2009-09-25 alik backup_events.test fails randomly
-backup.backup_external_non_win*          # BUG#45877
-backup.backup_logs                       # Bug#47698 2009-09-29 alik backup.backup_logs fails under valgrind
 backup.backup_xpfm_compat_backup_lctn2 @windows # Bug#46933 2009-08-26 alik backup_*_lctn2 tests fail on windows
 
 binlog.binlog_multi_engine               # joro : NDB tests marked as experimental as agreed with bochklin

=== modified file 'mysql-test/suite/backup/include/backup_ext.inc'
--- a/mysql-test/suite/backup/include/backup_ext.inc	2009-03-25 22:17:35 +0000
+++ b/mysql-test/suite/backup/include/backup_ext.inc	2009-11-13 12:10:39 +0000
@@ -28,3 +28,6 @@ my $F = IO::File->new("$vardir/tmp/mctf.
 print $F "let \$MYSQL_CONVERT_TABLE_FORMAT = $location;";
 
 EOF
+
+--source $MYSQLTEST_VARDIR/tmp/mctf.inc
+

=== modified file 'mysql-test/suite/backup/include/backup_xpfm_compat_backup.inc'
--- a/mysql-test/suite/backup/include/backup_xpfm_compat_backup.inc	2009-07-20 09:27:48 +0000
+++ b/mysql-test/suite/backup/include/backup_xpfm_compat_backup.inc	2009-11-18 15:27:51 +0000
@@ -897,6 +897,11 @@ DROP USER 'no_user'@'%';
 DROP USER 'bup_user1'@'%';
 DROP USER 'BUP_USER2';
 DROP USER 'BupUser3'@'%';
+# BUG#48850 : This test will hang on the DROP DATABASE commands.
+# Remove the FLUSH TABLES when this bug is fixed.
+--disable_query_log
+FLUSH TABLES;
+--enable_query_log
 DROP DATABASE bup_xpfm_compat_db1;
 DROP DATABASE BUP_XPFM_COMPAT_DB2;
 DROP DATABASE BupXPfmCompat_db3;

=== modified file 'mysql-test/suite/backup/r/backup_errors.result'
--- a/mysql-test/suite/backup/r/backup_errors.result	2009-10-21 12:15:53 +0000
+++ b/mysql-test/suite/backup/r/backup_errors.result	2009-11-17 20:18:50 +0000
@@ -595,6 +595,37 @@ SET SESSION DEBUG='-d';
 #
 # Test error handling by injecting errors into BACKUP
 #
+# non-existent database
+DROP DATABASE IF EXISTS db1;
+DROP DATABASE IF EXISTS db2;
+CREATE DATABASE db1;
+USE db1;
+CREATE TABLE db1_tab (i int);
+INSERT INTO  db1_tab VALUES (1), (2), (3);
+CREATE DATABASE db2;
+USE db2;
+CREATE TABLE db2_tab (v varchar(64));
+INSERT INTO db2_tab VALUES ("This is table db2_tab");
+# 
+# Backup without error injection
+# 
+SET SESSION DEBUG='-d';
+BACKUP DATABASE * TO 'all.bak' OVERWRITE;
+backup_id
+#
+SHOW WARNINGS;
+Level	Code	Message
+#
+# Error injection in user privileges checking
+#
+SET SESSION DEBUG='+d,ER_BACKUP_USER_PRIV_CHECK_add_db';
+BACKUP DATABASE db1 TO 'db1.bak' OVERWRITE;
+ERROR HY000: Failed to perform access privileges check for user 'root'.
+SET SESSION DEBUG='-d';
+SET SESSION DEBUG='+d,ER_BACKUP_USER_PRIV_CHECK_add_all_dbs';
+BACKUP DATABASE * TO 'all.bak' OVERWRITE;
+ERROR HY000: Failed to perform access privileges check for user 'root'.
+SET SESSION DEBUG='-d';
 #
 # Error injection in si_object.cc:get_database_stub
 #
@@ -606,3 +637,4 @@ SET SESSION DEBUG='-d';
 # Cleanup
 #
 DROP DATABASE db1;
+DROP DATABASE db2;

=== modified file 'mysql-test/suite/backup/r/backup_errors_compression.result'
--- a/mysql-test/suite/backup/r/backup_errors_compression.result	2009-10-23 15:41:56 +0000
+++ b/mysql-test/suite/backup/r/backup_errors_compression.result	2009-11-17 20:18:50 +0000
@@ -595,6 +595,37 @@ SET SESSION DEBUG='-d';
 #
 # Test error handling by injecting errors into BACKUP
 #
+# non-existent database
+DROP DATABASE IF EXISTS db1;
+DROP DATABASE IF EXISTS db2;
+CREATE DATABASE db1;
+USE db1;
+CREATE TABLE db1_tab (i int);
+INSERT INTO  db1_tab VALUES (1), (2), (3);
+CREATE DATABASE db2;
+USE db2;
+CREATE TABLE db2_tab (v varchar(64));
+INSERT INTO db2_tab VALUES ("This is table db2_tab");
+# 
+# Backup without error injection
+# 
+SET SESSION DEBUG='-d';
+BACKUP DATABASE * TO 'all.bak' OVERWRITE;
+backup_id
+#
+SHOW WARNINGS;
+Level	Code	Message
+#
+# Error injection in user privileges checking
+#
+SET SESSION DEBUG='+d,ER_BACKUP_USER_PRIV_CHECK_add_db';
+BACKUP DATABASE db1 TO 'db1.bak' OVERWRITE;
+ERROR HY000: Failed to perform access privileges check for user 'root'.
+SET SESSION DEBUG='-d';
+SET SESSION DEBUG='+d,ER_BACKUP_USER_PRIV_CHECK_add_all_dbs';
+BACKUP DATABASE * TO 'all.bak' OVERWRITE;
+ERROR HY000: Failed to perform access privileges check for user 'root'.
+SET SESSION DEBUG='-d';
 #
 # Error injection in si_object.cc:get_database_stub
 #
@@ -606,3 +637,4 @@ SET SESSION DEBUG='-d';
 # Cleanup
 #
 DROP DATABASE db1;
+DROP DATABASE db2;

=== modified file 'mysql-test/suite/backup/r/backup_external.result'
--- a/mysql-test/suite/backup/r/backup_external.result	2009-05-22 13:44:56 +0000
+++ b/mysql-test/suite/backup/r/backup_external.result	2009-11-16 19:20:34 +0000
@@ -184,6 +184,8 @@ Index_Comment	
 
 # Test 1: Use myisampack to compress the tables followed by myisamchk to 
 #         rebuild the indexes.
+# exec myisampack
+# exec myisamchk
 SHOW INDEX FROM db1.t1;;
 Table	t1
 Non_unique	1
@@ -203,9 +205,17 @@ BACKUP DATABASE db1 TO 'db1.bak';
 backup_id
 #
 DROP DATABASE db1;
+# RESTORE of a compressed MyISAM table issues two warnings:
+# "Table is read only" and "Deadlock found when trying to get lock".
+# This results from an internal call of FLUSH TABLES.
+# RESTORE can't get back its write lock on the now compressed table.
+# But it doesn't need the locks any more at this moment. So it's ok.
 RESTORE FROM 'db1.bak';
 backup_id
 #
+Warnings:
+#	1036	Table 't1' is read only
+#	1213	Deadlock found when trying to get lock; try restarting transaction
 SHOW INDEX FROM db1.t1;;
 Table	t1
 Non_unique	1
@@ -233,6 +243,9 @@ id	name
 # Use myisampack utility again after restore. Verify that utilities
 # are not affected and functions properly after backup and restore 
 # operation.
+# exec myisamchk
+# exec myisampack
+# exec myisamchk
 SHOW INDEX FROM db1.t1;;
 Table	t1
 Non_unique	1
@@ -261,14 +274,24 @@ id	name
 # Bug#42572 - Restore fails when myisampack used with -b option
 #
 # Use myisampack -b option to make backup of table datafile
+# exec myisamchk
+# exec myisampack
+# exec myisamchk
 BACKUP DATABASE db1 TO 'db1b.bak';
 backup_id
 #
+# RESTORE of a compressed MyISAM table issues two warnings:
+# "Table is read only" and "Deadlock found when trying to get lock".
+# This results from an internal call of FLUSH TABLES.
+# RESTORE can't get back its write lock on the now compressed table.
+# But it doesn't need the locks any more at this moment. So it's ok.
 RESTORE FROM 'db1b.bak' OVERWRITE;
 backup_id
 #
 Warnings:
 #	#	Renamed directory with unknown files to 'db1-#'
+#	#	Table 't1' is read only
+#	#	Deadlock found when trying to get lock; try restarting transaction
 SHOW TABLES FROM db1;
 Tables_in_db1
 t1
@@ -318,9 +341,17 @@ backup_id
 #
 DROP DATABASE db1;
 DROP DATABASE db2;
+# RESTORE of a compressed MyISAM table issues two warnings:
+# "Table is read only" and "Deadlock found when trying to get lock".
+# This results from an internal call of FLUSH TABLES.
+# RESTORE can't get back its write lock on the now compressed table.
+# But it doesn't need the locks any more at this moment. So it's ok.
 RESTORE FROM 'db12.bak';
 backup_id
 #
+Warnings:
+#	1036	Table 't1' is read only
+#	1213	Deadlock found when trying to get lock; try restarting transaction
 CHECKSUM TABLE db1.t1;
 Table	Checksum
 db1.t1	261218912
@@ -505,9 +536,17 @@ backup_id
 #
 DROP DATABASE db1;
 DROP DATABASE db2;
+# RESTORE of a compressed MyISAM table issues two warnings:
+# "Table is read only" and "Deadlock found when trying to get lock".
+# This results from an internal call of FLUSH TABLES.
+# RESTORE can't get back its write lock on the now compressed table.
+# But it doesn't need the locks any more at this moment. So it's ok.
 RESTORE FROM 'db12.bak';
 backup_id
 #
+Warnings:
+#	1036	Table 't1' is read only
+#	1213	Deadlock found when trying to get lock; try restarting transaction
 SELECT COUNT(*) FROM db1.t1 WHERE id < 5;
 COUNT(*)
 128

=== modified file 'mysql-test/suite/backup/r/backup_intr_errors.result'
--- a/mysql-test/suite/backup/r/backup_intr_errors.result	2009-10-12 09:08:34 +0000
+++ b/mysql-test/suite/backup/r/backup_intr_errors.result	2009-11-16 19:20:34 +0000
@@ -112,6 +112,8 @@ SHOW WARNINGS;
 Level	Code	Message
 Error	<error-code>	Query execution was interrupted
 Error	<error-code>	Can't shut down Snapshot restore driver(s)
+Error	<error-code>	Query execution was interrupted
+Error	<error-code>	Query execution was interrupted
 Warning	<error-code>	Operation aborted - data might be corrupted
 Error	<error-code>	Backup/Restore: Error on close of backup stream
 #
@@ -238,6 +240,8 @@ SHOW WARNINGS;
 Level	Code	Message
 Error	<error-code>	Query execution was interrupted
 Error	<error-code>	Can't shut down Default restore driver(s)
+Error	<error-code>	Query execution was interrupted
+Error	<error-code>	Query execution was interrupted
 Warning	<error-code>	Operation aborted - data might be corrupted
 Error	<error-code>	Backup/Restore: Error on close of backup stream
 #

=== modified file 'mysql-test/suite/backup/r/backup_logs.result'
--- a/mysql-test/suite/backup/r/backup_logs.result	2009-11-04 14:18:21 +0000
+++ b/mysql-test/suite/backup/r/backup_logs.result	2009-11-10 17:24:18 +0000
@@ -205,12 +205,6 @@ Turn off debugging session.
 SET SESSION debug="-d";
 SET time_zone='+0:00';
 SELECT now() INTO @stop_backup;
-We calculate the timedifference between backup start time and stop
-time. If this difference is '0', then backup start time and stop time
-are same.
-SELECT timediff(@stop_backup, @start_backup) > 5;
-timediff(@stop_backup, @start_backup) > 5
-0
 
 Now verify actual start time / stop time of backup and start time /
 stop time from backup_history table. If the both times are same, 

=== modified file 'mysql-test/suite/backup/r/backup_logs_output.result'
--- a/mysql-test/suite/backup/r/backup_logs_output.result	2009-10-26 09:16:48 +0000
+++ b/mysql-test/suite/backup/r/backup_logs_output.result	2009-11-16 15:21:34 +0000
@@ -238,6 +238,51 @@ count(*)
 6
 FLUSH BACKUP LOGS;
 Test flush-backup-logs from mysqladmin
+#
+# Test purge-backup-logs from mysqladmin
+#
+#
+# Do another backup here then try next version of purge backup logs 
+#
+BACKUP DATABASE bup_log TO 'bup_log.bak';
+backup_id
+#
+SELECT count(*) FROM mysql.backup_history;
+count(*)
+1
+SELECT count(*) FROM mysql.backup_progress;
+count(*)
+6
+#
+# Test purge-backup-logs-to from mysqladmin
+#
+SELECT count(*) FROM mysql.backup_history;
+count(*)
+0
+SELECT count(*) FROM mysql.backup_progress;
+count(*)
+0
+#
+# Do another backup here then try next version of purge backup logs 
+#
+BACKUP DATABASE bup_log TO 'bup_log.bak';
+backup_id
+#
+SELECT count(*) FROM mysql.backup_history;
+count(*)
+1
+SELECT count(*) FROM mysql.backup_progress;
+count(*)
+6
+#
+# Test purge-backup-logs-date from mysqladmin
+#
+SELECT count(*) FROM mysql.backup_history;
+count(*)
+0
+SELECT count(*) FROM mysql.backup_progress;
+count(*)
+0
 SET GLOBAL backup_history_log=0;
 SET GLOBAL backup_progress_log=0;
 Should show 'OFF'

=== modified file 'mysql-test/suite/backup/r/backup_myisam.result'
--- a/mysql-test/suite/backup/r/backup_myisam.result	2009-02-13 12:40:13 +0000
+++ b/mysql-test/suite/backup/r/backup_myisam.result	2009-11-16 19:20:34 +0000
@@ -15,12 +15,22 @@ INSERT INTO mysql_db1.t1 SELECT * FROM m
 INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1;
 INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1;
 FLUSH TABLE mysql_db1.t1;
+# exec myisampack
+# exec myisamchk
 BACKUP DATABASE mysql_db1 to 'bup_myisam.bak';
 backup_id
-#
+###
+# RESTORE of a compressed MyISAM table issues two warnings:
+# "Table is read only" and "Deadlock found when trying to get lock".
+# This results from an internal call of FLUSH TABLES.
+# RESTORE can't get back its write lock on the now compressed table.
+# But it doesn't need the locks any more at this moment. So it's ok.
 RESTORE FROM 'bup_myisam.bak' OVERWRITE;
 backup_id
-#
+###
+Warnings:
+###	1036	Table 't1' is read only
+###	1213	Deadlock found when trying to get lock; try restarting transaction
 SELECT COUNT(*) FROM mysql_db1.t1 WHERE c2 < 5;
 COUNT(*)
 128

=== modified file 'mysql-test/suite/backup/r/backup_myisam_coverage.result'
--- a/mysql-test/suite/backup/r/backup_myisam_coverage.result	2008-12-30 12:13:31 +0000
+++ b/mysql-test/suite/backup/r/backup_myisam_coverage.result	2009-11-16 19:20:34 +0000
@@ -12,13 +12,23 @@ INSERT INTO mysql_db1.t1 SELECT * FROM m
 INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1;
 INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1;
 FLUSH TABLE mysql_db1.t1;
+# exec myisampack
+# exec myisamchk
 BACKUP DATABASE mysql_db1 to 'bup_myisam3.bak';
 backup_id
 #
 SET debug='d,Backup_restore_ctx_unlock_tables_alloc';
+# RESTORE of a compressed MyISAM table issues two warnings:
+# "Table is read only" and "Deadlock found when trying to get lock".
+# This results from an internal call of FLUSH TABLES.
+# RESTORE can't get back its write lock on the now compressed table.
+# But it doesn't need the locks any more at this moment. So it's ok.
 RESTORE FROM 'bup_myisam3.bak' OVERWRITE;
 backup_id
 #
+Warnings:
+#	1036	Table 't1' is read only
+#	1213	Deadlock found when trying to get lock; try restarting transaction
 SELECT COUNT(*) FROM mysql_db1.t1 WHERE c2 < 5;
 COUNT(*)
 128

=== modified file 'mysql-test/suite/backup/r/backup_myisam_sync.result'
--- a/mysql-test/suite/backup/r/backup_myisam_sync.result	2009-04-14 13:40:06 +0000
+++ b/mysql-test/suite/backup/r/backup_myisam_sync.result	2009-11-16 19:20:34 +0000
@@ -76,7 +76,57 @@ VARIABLE_NAME LIKE 'Key_blocks_%used';
 key_cache_is_enabled
 1
 
-# final cleanup
+# cleanup
 USE test;
 DROP DATABASE mysqltest;
 SET DEBUG_SYNC= 'RESET';
+#
+# Bug#40944 - Backup: crash after myisampack
+# Patch #2
+#
+CREATE DATABASE bup_myisam_sync_db1;
+CREATE TABLE bup_myisam_sync_db1.t1 (c1 VARCHAR(5), c2 int) ENGINE=MyISAM;
+CREATE INDEX i1 ON bup_myisam_sync_db1.t1 (c1, c2);
+INSERT INTO bup_myisam_sync_db1.t1 VALUES ('A',1);
+INSERT INTO bup_myisam_sync_db1.t1 SELECT * FROM bup_myisam_sync_db1.t1;
+INSERT INTO bup_myisam_sync_db1.t1 SELECT * FROM bup_myisam_sync_db1.t1;
+INSERT INTO bup_myisam_sync_db1.t1 SELECT * FROM bup_myisam_sync_db1.t1;
+INSERT INTO bup_myisam_sync_db1.t1 SELECT * FROM bup_myisam_sync_db1.t1;
+INSERT INTO bup_myisam_sync_db1.t1 SELECT * FROM bup_myisam_sync_db1.t1;
+INSERT INTO bup_myisam_sync_db1.t1 SELECT * FROM bup_myisam_sync_db1.t1;
+INSERT INTO bup_myisam_sync_db1.t1 SELECT * FROM bup_myisam_sync_db1.t1;
+FLUSH TABLE bup_myisam_sync_db1.t1;
+# exec myisampack
+# exec myisamchk
+BACKUP DATABASE bup_myisam_sync_db1 to 'bup_myisam_sync_db1.bak';
+backup_id
+#
+DROP DATABASE bup_myisam_sync_db1;
+SET DEBUG_SYNC= 'after_restore_locks_tables SIGNAL restore_locked
+                 WAIT_FOR restore_finish';
+RESTORE FROM 'bup_myisam_sync_db1.bak';
+#
+# connection con1
+SET DEBUG_SYNC= 'now WAIT_FOR restore_locked';
+SET DEBUG_SYNC= 'wait_for_lock SIGNAL restore_finish';
+SELECT COUNT(*) FROM bup_myisam_sync_db1.t1 WHERE c2 < 5;
+#
+# connection default
+# RESTORE of a compressed MyISAM table issues two warnings:
+# "Table is read only" and "Deadlock found when trying to get lock".
+# This results from an internal call of FLUSH TABLES.
+# RESTORE can't get back its write lock on the now compressed table.
+# But it doesn't need the locks any more at this moment. So it's ok.
+backup_id
+###
+Warnings:
+###	1036	Table 't1' is read only
+###	1213	Deadlock found when trying to get lock; try restarting transaction
+#
+# connection con1
+COUNT(*)
+128
+#
+# connection default
+SET DEBUG_SYNC= 'RESET';
+DROP DATABASE bup_myisam_sync_db1;

=== modified file 'mysql-test/suite/backup/r/backup_no_engine.result'
--- a/mysql-test/suite/backup/r/backup_no_engine.result	2009-06-18 11:28:01 +0000
+++ b/mysql-test/suite/backup/r/backup_no_engine.result	2009-11-09 10:56:12 +0000
@@ -1,3 +1,6 @@
+Suppress this error in the server log
+call mtr.add_suppression("Can't access storage engine of table ");
+
 DROP DATABASE IF EXISTS db;
 CREATE DATABASE db;
 CREATE TABLE db.t1 (a int, b char(32));
@@ -6,19 +9,10 @@ Tables_in_db
 t1
 t2
 BACKUP DATABASE db TO "db.backup";
-backup_id
-#
-DROP DATABASE db;
-RESTORE FROM "db.backup";
-backup_id
-#
-SHOW TABLES IN db;
-Tables_in_db
-t1
-SHOW CREATE TABLE db.t1;
-Table	Create Table
-t1	CREATE TABLE `t1` (
-  `a` int(11) DEFAULT NULL,
-  `b` char(32) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ERROR 42000: Unknown storage engine 'PARADOX'
+SHOW WARNINGS;
+Level	Code	Message
+Error	1286	Unknown storage engine 'PARADOX'
+Error	1642	Can't access storage engine of table `db`.`t2`
+Warning	1777	Operation aborted
 DROP DATABASE db;

=== added file 'mysql-test/suite/backup/r/backup_restore_locking.result'
--- a/mysql-test/suite/backup/r/backup_restore_locking.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/r/backup_restore_locking.result	2009-11-16 19:20:34 +0000
@@ -0,0 +1,148 @@
+call mtr.add_suppression("Restore: Open and lock tables failed in RESTORE");
+#
+# Precautionary cleanup
+#
+SET DEBUG_SYNC= 'RESET';
+SET @old_sessiondebug=@@session.debug;
+DROP DATABASE IF EXISTS bup_reslock_db1;
+#
+# Bug#41716 - Backup Error when sending data (for table #1)
+#             to Default/Snapshot restore driver
+#
+CREATE DATABASE bup_reslock_db1;
+USE bup_reslock_db1;
+CREATE TABLE t1 (c1 INT, c2 VARCHAR(100), UNIQUE(c1)) ENGINE=MEMORY;
+INSERT INTO t1 VALUES (1,"abc");
+BACKUP DATABASE bup_reslock_db1 TO 'bup_reslock_db1.bak';
+backup_id
+###
+DROP DATABASE bup_reslock_db1;
+SET DEBUG_SYNC= 'before_restore_locks_tables SIGNAL restore_before_locking
+                 WAIT_FOR restore_finish';
+RESTORE FROM 'bup_reslock_db1.bak';
+#
+# connection con1
+SET DEBUG_SYNC= 'now WAIT_FOR restore_before_locking';
+INSERT INTO bup_reslock_db1.t1 VALUES(1,"def");
+SET DEBUG_SYNC= 'now SIGNAL restore_finish';
+#
+# connection default, retrieve RESTORE result.
+backup_id
+###
+SET DEBUG_SYNC= 'RESET';
+SELECT * FROM t1;
+c1	c2
+1	abc
+FLUSH TABLE t1;
+SELECT * FROM t1;
+c1	c2
+1	abc
+USE test;
+DROP DATABASE bup_reslock_db1;
+#
+# WL#4844 - Implement a locking scheme for RESTORE
+#
+CREATE DATABASE bup_reslock_db1;
+USE bup_reslock_db1;
+CREATE TABLE t1 (c1 INT, c2 VARCHAR(100), UNIQUE(c1)) ENGINE=MEMORY;
+INSERT INTO t1 VALUES (0,"backup");
+BACKUP DATABASE bup_reslock_db1 TO 'bup_reslock_db1.bak';
+backup_id
+###
+DROP DATABASE bup_reslock_db1;
+SET DEBUG_SYNC= 'after_restore_lock_tables_for_write
+                 SIGNAL waiting WAIT_FOR continue';
+SET DEBUG_SYNC= 'after_restore_truncate_tables
+                 SIGNAL waiting WAIT_FOR continue';
+SET DEBUG_SYNC= 'before_restore_flush_tables
+                 SIGNAL waiting WAIT_FOR continue';
+SET DEBUG_SYNC= 'before_restore_unlock_tables
+                 SIGNAL waiting WAIT_FOR continue';
+RESTORE FROM 'bup_reslock_db1.bak';
+#
+# connection con1
+SET DEBUG_SYNC= 'now WAIT_FOR waiting';
+SET DEBUG_SYNC= 'wait_for_lock SIGNAL lock_wait';
+INSERT INTO bup_reslock_db1.t1 VALUES(1,"after_lock_tables");
+#
+# connection con2
+SET DEBUG_SYNC= 'now WAIT_FOR lock_wait';
+SET DEBUG_SYNC= 'now SIGNAL continue WAIT_FOR waiting';
+SET DEBUG_SYNC= 'wait_for_lock SIGNAL lock_wait';
+INSERT INTO bup_reslock_db1.t1 VALUES(2,"after_truncate_tables");
+#
+# connection con3
+SET DEBUG_SYNC= 'now SIGNAL continue WAIT_FOR waiting';
+SET DEBUG_SYNC= 'wait_for_lock SIGNAL lock_wait';
+INSERT INTO bup_reslock_db1.t1 VALUES(3,"before_flush_tables");
+#
+# connection con4
+SET DEBUG_SYNC= 'now WAIT_FOR lock_wait';
+SET DEBUG_SYNC= 'now SIGNAL continue WAIT_FOR waiting';
+SET DEBUG_SYNC= 'wait_for_lock SIGNAL lock_wait';
+INSERT INTO bup_reslock_db1.t1 VALUES(4,"before_unlock_tables");
+#
+# connection con5
+SET DEBUG_SYNC= 'now WAIT_FOR lock_wait';
+SELECT state, info FROM INFORMATION_SCHEMA.PROCESSLIST;
+state	info
+executing	SELECT state, info FROM INFORMATION_SCHEMA.PROCESSLIST
+Table lock	INSERT INTO bup_reslock_db1.t1 VALUES(4,"before_unlock_tables")
+Table lock	INSERT INTO bup_reslock_db1.t1 VALUES(3,"before_flush_tables")
+Table lock	INSERT INTO bup_reslock_db1.t1 VALUES(2,"after_truncate_tables")
+Table lock	INSERT INTO bup_reslock_db1.t1 VALUES(1,"after_lock_tables")
+debug sync point: before_restore_unlock_tables	RESTORE FROM 'bup_reslock_db1.bak'
+SET DEBUG_SYNC= 'now SIGNAL continue';
+#
+# connection default, retrieve RESTORE result
+backup_id
+###
+SET DEBUG_SYNC= 'RESET';
+#
+# connection con1, retrieve INSERT result.
+#
+# connection con2, retrieve INSERT result.
+#
+# connection con3, retrieve INSERT result.
+#
+# connection con4, retrieve INSERT result.
+#
+# connection default
+SELECT * FROM t1 ORDER BY c1;
+c1	c2
+0	backup
+1	after_lock_tables
+2	after_truncate_tables
+3	before_flush_tables
+4	before_unlock_tables
+FLUSH TABLE t1;
+SELECT * FROM t1 ORDER BY c1;
+c1	c2
+0	backup
+1	after_lock_tables
+2	after_truncate_tables
+3	before_flush_tables
+4	before_unlock_tables
+USE test;
+DROP DATABASE bup_reslock_db1;
+#
+# WL#4844 - Implement a locking scheme for RESTORE
+# Code coverage tests.
+#
+SET DEBUG='+d,error_inject_truncate_enter';
+RESTORE FROM 'bup_reslock_db1.bak';
+ERROR HY000: Open and lock tables failed in RESTORE
+SET debug=@old_sessiondebug;
+DROP DATABASE bup_reslock_db1;
+SET DEBUG_SYNC='after_restore_truncate_tables SIGNAL sync WAIT_FOR go';
+RESTORE FROM 'bup_reslock_db1.bak';
+#
+# connection con1
+SET DEBUG_SYNC= 'now WAIT_FOR sync';
+KILL QUERY ##;
+SET DEBUG_SYNC= 'now SIGNAL go';
+#
+# connection default, retrieve RESTORE result.
+ERROR 70100: Query execution was interrupted
+SET DEBUG_SYNC= 'RESET';
+DROP DATABASE bup_reslock_db1;

=== modified file 'mysql-test/suite/backup/t/backup_errors.test'
--- a/mysql-test/suite/backup/t/backup_errors.test	2009-10-21 12:15:53 +0000
+++ b/mysql-test/suite/backup/t/backup_errors.test	2009-11-17 20:18:50 +0000
@@ -697,6 +697,45 @@ SET SESSION DEBUG='-d';
 --echo # Test error handling by injecting errors into BACKUP
 --echo #
 
+--echo # non-existent database
+--disable_warnings
+DROP DATABASE IF EXISTS db1;
+DROP DATABASE IF EXISTS db2;
+--enable_warnings
+
+CREATE DATABASE db1;
+USE db1;
+CREATE TABLE db1_tab (i int);
+INSERT INTO  db1_tab VALUES (1), (2), (3);
+
+CREATE DATABASE db2;
+USE db2;
+CREATE TABLE db2_tab (v varchar(64));
+INSERT INTO db2_tab VALUES ("This is table db2_tab");
+
+--echo # 
+--echo # Backup without error injection
+--echo # 
+SET SESSION DEBUG='-d';
+--replace_column 1 #
+BACKUP DATABASE * TO 'all.bak' OVERWRITE;
+SHOW WARNINGS;
+
+--echo #
+--echo # Error injection in user privileges checking
+--echo #
+SET SESSION DEBUG='+d,ER_BACKUP_USER_PRIV_CHECK_add_db';
+
+--error ER_BACKUP_USER_PRIV_CHECK
+BACKUP DATABASE db1 TO 'db1.bak' OVERWRITE;
+SET SESSION DEBUG='-d';
+
+SET SESSION DEBUG='+d,ER_BACKUP_USER_PRIV_CHECK_add_all_dbs';
+
+--error ER_BACKUP_USER_PRIV_CHECK
+BACKUP DATABASE * TO 'all.bak' OVERWRITE;
+SET SESSION DEBUG='-d';
+
 --echo #
 --echo # Error injection in si_object.cc:get_database_stub
 --echo #
@@ -710,6 +749,7 @@ SET SESSION DEBUG='-d';
 --echo #
 
 DROP DATABASE db1;
+DROP DATABASE db2;
 
 --remove_file $MYSQLD_DATADIR/errorinject.bak
 

=== modified file 'mysql-test/suite/backup/t/backup_external.test'
--- a/mysql-test/suite/backup/t/backup_external.test	2009-05-22 13:44:56 +0000
+++ b/mysql-test/suite/backup/t/backup_external.test	2009-11-16 19:20:34 +0000
@@ -108,7 +108,9 @@ INSERT INTO db2.t2 VALUES
 # Myisamchk uses -s for silent mode, r for recovery and q for quick repair of
 # datafiles
 
+--echo # exec myisampack
 --exec $MYISAMPACK -s $MYSQLD_DATADIR/db1/t1.MYI
+--echo # exec myisamchk
 --exec $MYISAMCHK -srq $MYSQLD_DATADIR/db1/t1.MYI
 
 # Check the indexes in the table db1.t1
@@ -123,6 +125,11 @@ BACKUP DATABASE db1 TO 'db1.bak';
 DROP DATABASE db1;
 
 # Perform restore
+--echo # RESTORE of a compressed MyISAM table issues two warnings:
+--echo # "Table is read only" and "Deadlock found when trying to get lock".
+--echo # This results from an internal call of FLUSH TABLES.
+--echo # RESTORE can't get back its write lock on the now compressed table.
+--echo # But it doesn't need the locks any more at this moment. So it's ok.
 --replace_column 1 #
 RESTORE FROM 'db1.bak';
 
@@ -137,8 +144,11 @@ SELECT * FROM db1.t1 LIMIT 4;
 --echo # are not affected and functions properly after backup and restore 
 --echo # operation.
 
+--echo # exec myisamchk
 --exec $MYISAMCHK -s --unpack $MYSQLD_DATADIR/db1/t1.MYI
+--echo # exec myisampack
 --exec $MYISAMPACK -s $MYSQLD_DATADIR/db1/t1.MYI
+--echo # exec myisamchk
 --exec $MYISAMCHK -srq $MYSQLD_DATADIR/db1/t1.MYI
 
 # Check the indexes in the table db1.t1
@@ -154,8 +164,11 @@ SELECT * FROM db1.t1 LIMIT 4;
 --echo #
 --echo # Use myisampack -b option to make backup of table datafile
 
+--echo # exec myisamchk
 --exec $MYISAMCHK -s --unpack $MYSQLD_DATADIR/db1/t1.MYI
+--echo # exec myisampack
 --exec $MYISAMPACK -s -b $MYSQLD_DATADIR/db1/t1.MYI
+--echo # exec myisamchk
 --exec $MYISAMCHK -srq $MYSQLD_DATADIR/db1/t1.MYI
 
 # Execute backup operation
@@ -163,6 +176,11 @@ SELECT * FROM db1.t1 LIMIT 4;
 BACKUP DATABASE db1 TO 'db1b.bak';
 
 # Perform restore
+--echo # RESTORE of a compressed MyISAM table issues two warnings:
+--echo # "Table is read only" and "Deadlock found when trying to get lock".
+--echo # This results from an internal call of FLUSH TABLES.
+--echo # RESTORE can't get back its write lock on the now compressed table.
+--echo # But it doesn't need the locks any more at this moment. So it's ok.
 # Mask UUID and path delimiter.
 --replace_regex /db1-[^']*/db1-#/ /'\.[\/\\]/'/
 # Mask backup_id and warning numbers.
@@ -220,6 +238,11 @@ DROP DATABASE db1;
 DROP DATABASE db2;
 
 # Perform restore
+--echo # RESTORE of a compressed MyISAM table issues two warnings:
+--echo # "Table is read only" and "Deadlock found when trying to get lock".
+--echo # This results from an internal call of FLUSH TABLES.
+--echo # RESTORE can't get back its write lock on the now compressed table.
+--echo # But it doesn't need the locks any more at this moment. So it's ok.
 --replace_column 1 #
 RESTORE FROM 'db12.bak';
 
@@ -308,6 +331,11 @@ DROP DATABASE db1;
 DROP DATABASE db2;
 
 # Perform restore
+--echo # RESTORE of a compressed MyISAM table issues two warnings:
+--echo # "Table is read only" and "Deadlock found when trying to get lock".
+--echo # This results from an internal call of FLUSH TABLES.
+--echo # RESTORE can't get back its write lock on the now compressed table.
+--echo # But it doesn't need the locks any more at this moment. So it's ok.
 --replace_column 1 #
 RESTORE FROM 'db12.bak';
 

=== modified file 'mysql-test/suite/backup/t/backup_external_non_win.test'
--- a/mysql-test/suite/backup/t/backup_external_non_win.test	2009-06-13 10:12:02 +0000
+++ b/mysql-test/suite/backup/t/backup_external_non_win.test	2009-11-13 12:10:39 +0000
@@ -12,6 +12,11 @@
 --source suite/backup/include/backup_ext.inc
 --source suite/backup/include/have_dbi.inc
 
+if(`select "$MYSQL_CONVERT_TABLE_FORMAT" NOT LIKE '%convert_table_format%'`)
+{
+--skip Could not find mysql_convert_table_format utility.
+}
+
 let $MYSQLD_BACKUPDIR = `select @@backupdir`;
 let $MYSQLD_DATADIR= `select @@datadir`;
 
@@ -75,7 +80,6 @@ INSERT INTO db2.t1(b,c) VALUES
 # Changing the storage engine for db1
 SHOW CREATE TABLE db1.t1;
 
-source $MYSQLTEST_VARDIR/tmp/mctf.inc;
 --exec perl $MYSQL_CONVERT_TABLE_FORMAT --user=root -S $MASTER_MYSOCK --port=$MASTER_MYPORT  --type=innodb db1
 
 --echo
@@ -96,7 +100,6 @@ RESTORE FROM 'db1.bak';
 SHOW CREATE TABLE db1.t1;
 
 --echo # Changing the storage engine back to myisam
-source $MYSQLTEST_VARDIR/tmp/mctf.inc;
 --exec perl $MYSQL_CONVERT_TABLE_FORMAT -u root -S $MASTER_MYSOCK --port=$MASTER_MYPORT  db1
 
 SHOW CREATE TABLE db1.t1;
@@ -156,7 +159,6 @@ BACKUP DATABASE db1 TO 'db1.bak';
 --echo # tables in db1
 
 --disable_warnings
-source $MYSQLTEST_VARDIR/tmp/mctf.inc;
 --exec perl $MYSQL_CONVERT_TABLE_FORMAT -u root -S $MASTER_MYSOCK --port=$MASTER_MYPORT  --type=myisam db1
 --enable_warnings
 
@@ -191,7 +193,6 @@ RESTORE FROM 'db1.bak' OVERWRITE;
 --echo # Verify that tablespace is restored from db1.t2
 SHOW CREATE TABLE db1.t2;
 
-source $MYSQLTEST_VARDIR/tmp/mctf.inc;
 --exec perl $MYSQL_CONVERT_TABLE_FORMAT -u root -S $MASTER_MYSOCK --port=$MASTER_MYPORT  --type=falcon db1
 
 SHOW CREATE TABLE db1.tpl;
@@ -224,7 +225,6 @@ DROP VIEW db2.v1;
 --remove_file $MYSQLD_BACKUPDIR/db1.bak
 
 --echo # Changing the storage engine back to myisam after restore
-source $MYSQLTEST_VARDIR/tmp/mctf.inc;
 --exec perl $MYSQL_CONVERT_TABLE_FORMAT -u root -S $MASTER_MYSOCK --port=$MASTER_MYPORT db1
 
 SHOW CREATE TABLE db1.t1;

=== modified file 'mysql-test/suite/backup/t/backup_external_non_win_not_falcon.test'
--- a/mysql-test/suite/backup/t/backup_external_non_win_not_falcon.test	2009-06-30 07:51:04 +0000
+++ b/mysql-test/suite/backup/t/backup_external_non_win_not_falcon.test	2009-11-13 12:10:39 +0000
@@ -9,6 +9,11 @@
 --source suite/backup/include/backup_ext.inc
 --source suite/backup/include/have_dbi.inc
 
+if(`select "$MYSQL_CONVERT_TABLE_FORMAT" NOT LIKE '%convert_table_format%'`)
+{
+--skip Could not find mysql_convert_table_format utility.
+}
+
 let $MYSQLD_BACKUPDIR = `select @@backupdir`;
 let $MYSQLD_DATADIR= `select @@datadir`;
 
@@ -69,7 +74,6 @@ INSERT INTO db2.t1(b,c) VALUES
 # Changing the storage engine for db1
 SHOW CREATE TABLE db1.t1;
 
-source $MYSQLTEST_VARDIR/tmp/mctf.inc;
 --exec $MYSQL_CONVERT_TABLE_FORMAT --user=root -S $MASTER_MYSOCK --port=$MASTER_MYPORT  --type=innodb db1
 
 --echo
@@ -90,7 +94,6 @@ RESTORE FROM 'db1.bak';
 SHOW CREATE TABLE db1.t1;
 
 --echo # Changing the storage engine back to myisam
-source $MYSQLTEST_VARDIR/tmp/mctf.inc;
 --exec $MYSQL_CONVERT_TABLE_FORMAT -u root -S $MASTER_MYSOCK --port=$MASTER_MYPORT  db1
 
 SHOW CREATE TABLE db1.t1;
@@ -149,7 +152,6 @@ BACKUP DATABASE db1 TO 'db1.bak';
 --echo # tables in db1
 
 --disable_warnings
-source $MYSQLTEST_VARDIR/tmp/mctf.inc;
 --exec $MYSQL_CONVERT_TABLE_FORMAT -u root -S $MASTER_MYSOCK --port=$MASTER_MYPORT  --type=myisam db1
 --enable_warnings
 
@@ -182,7 +184,6 @@ RESTORE FROM 'db1.bak' OVERWRITE;
 
 SHOW CREATE TABLE db1.t2;
 
-source $MYSQLTEST_VARDIR/tmp/mctf.inc;
 --exec $MYSQL_CONVERT_TABLE_FORMAT -u root -S $MASTER_MYSOCK --port=$MASTER_MYPORT  --type=innodb db1
 
 SHOW CREATE TABLE db1.tpl;
@@ -215,7 +216,6 @@ DROP VIEW db2.v1;
 --remove_file $MYSQLD_BACKUPDIR/db1.bak
 
 --echo # Changing the storage engine back to myisam after restore
-source $MYSQLTEST_VARDIR/tmp/mctf.inc;
 --exec $MYSQL_CONVERT_TABLE_FORMAT -u root -S $MASTER_MYSOCK --port=$MASTER_MYPORT db1
 
 SHOW CREATE TABLE db1.t1;

=== modified file 'mysql-test/suite/backup/t/backup_logs.test'
--- a/mysql-test/suite/backup/t/backup_logs.test	2009-10-12 09:08:34 +0000
+++ b/mysql-test/suite/backup/t/backup_logs.test	2009-11-10 17:24:18 +0000
@@ -289,12 +289,6 @@ connection con1;
 SET time_zone='+0:00';
 SELECT now() INTO @stop_backup;
 
---echo We calculate the timedifference between backup start time and stop
---echo time. If this difference is '0', then backup start time and stop time
---echo are same.
-
-SELECT timediff(@stop_backup, @start_backup) > 5;
-
 --echo
 --echo Now verify actual start time / stop time of backup and start time /
 --echo stop time from backup_history table. If the both times are same, 

=== modified file 'mysql-test/suite/backup/t/backup_logs_output.test'
--- a/mysql-test/suite/backup/t/backup_logs_output.test	2009-10-26 09:16:48 +0000
+++ b/mysql-test/suite/backup/t/backup_logs_output.test	2009-11-16 15:21:34 +0000
@@ -263,6 +263,54 @@ FLUSH BACKUP LOGS;
 
 --exec $MYSQLADMIN --no-defaults --default-character-set=latin1 -S $MASTER_MYSOCK -P $MASTER_MYPORT  -u root --password= flush-backup-logs 2>&1
                                                     
+#
+# BUG#48353 - add 'purge backup logs' to mysqladmin.
+#
+# 'purge backup logs' reopens log files (PURGE BACKUP LOGS only).
+# Log files are created irrespective of log_backup_output options.
+# Test 'purge-backup-logs' from mysqladmin for log_backup_ouput=TABLE,FILE.
+#
+
+--echo #
+--echo # Test purge-backup-logs from mysqladmin
+--echo #
+--exec $MYSQLADMIN --no-defaults --default-character-set=latin1 -S $MASTER_MYSOCK -P $MASTER_MYPORT  -u root --password= purge-backup-logs 2>&1
+
+--echo #
+--echo # Do another backup here then try next version of purge backup logs 
+--echo #
+--remove_file $MYSQLD_BACKUPDIR/bup_log.bak
+--replace_column 1 #
+BACKUP DATABASE bup_log TO 'bup_log.bak';
+
+SELECT count(*) FROM mysql.backup_history;
+SELECT count(*) FROM mysql.backup_progress;
+
+--echo #
+--echo # Test purge-backup-logs-to from mysqladmin
+--echo #
+--exec $MYSQLADMIN --no-defaults --default-character-set=latin1 -S $MASTER_MYSOCK -P $MASTER_MYPORT  -u root --password= purge-backup-logs-id 99999 2>&1
+
+SELECT count(*) FROM mysql.backup_history;
+SELECT count(*) FROM mysql.backup_progress;
+
+--echo #
+--echo # Do another backup here then try next version of purge backup logs 
+--echo #
+--remove_file $MYSQLD_BACKUPDIR/bup_log.bak
+--replace_column 1 #
+BACKUP DATABASE bup_log TO 'bup_log.bak';
+
+SELECT count(*) FROM mysql.backup_history;
+SELECT count(*) FROM mysql.backup_progress;
+
+--echo #
+--echo # Test purge-backup-logs-date from mysqladmin
+--echo #
+--exec $MYSQLADMIN --no-defaults --default-character-set=latin1 -S $MASTER_MYSOCK -P $MASTER_MYPORT  -u root --password= purge-backup-logs-date '2024-12-31 23:15:10' 2>&1
+
+SELECT count(*) FROM mysql.backup_history;
+SELECT count(*) FROM mysql.backup_progress;
 
 --file_exists $MYSQLD_DATADIR/backup_history.log
 --file_exists $MYSQLD_DATADIR/backup_progress.log

=== modified file 'mysql-test/suite/backup/t/backup_myisam.test'
--- a/mysql-test/suite/backup/t/backup_myisam.test	2009-02-24 20:57:21 +0000
+++ b/mysql-test/suite/backup/t/backup_myisam.test	2009-11-16 19:20:34 +0000
@@ -32,12 +32,20 @@ INSERT INTO mysql_db1.t1 SELECT * FROM m
 INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1;
 FLUSH TABLE mysql_db1.t1;
 #
+--echo # exec myisampack
 --exec $MYISAMPACK -s $MYSQLD_DATADIR/mysql_db1/t1
+--echo # exec myisamchk
 --exec $MYISAMCHK -srq $MYSQLD_DATADIR/mysql_db1/t1
 #
---replace_column 1 #
+--replace_column 1 ###
 BACKUP DATABASE mysql_db1 to 'bup_myisam.bak';
---replace_column 1 #
+#
+--echo # RESTORE of a compressed MyISAM table issues two warnings:
+--echo # "Table is read only" and "Deadlock found when trying to get lock".
+--echo # This results from an internal call of FLUSH TABLES.
+--echo # RESTORE can't get back its write lock on the now compressed table.
+--echo # But it doesn't need the locks any more at this moment. So it's ok.
+--replace_column 1 ###
 RESTORE FROM 'bup_myisam.bak' OVERWRITE;
 #
 SELECT COUNT(*) FROM mysql_db1.t1 WHERE c2 < 5;

=== modified file 'mysql-test/suite/backup/t/backup_myisam_coverage.test'
--- a/mysql-test/suite/backup/t/backup_myisam_coverage.test	2009-02-24 20:57:21 +0000
+++ b/mysql-test/suite/backup/t/backup_myisam_coverage.test	2009-11-16 19:20:34 +0000
@@ -33,7 +33,9 @@ INSERT INTO mysql_db1.t1 SELECT * FROM m
 INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1;
 FLUSH TABLE mysql_db1.t1;
 #
+--echo # exec myisampack
 --exec $MYISAMPACK -s $MYSQLD_DATADIR/mysql_db1/t1
+--echo # exec myisamchk
 --exec $MYISAMCHK -srq $MYSQLD_DATADIR/mysql_db1/t1
 #
 --replace_column 1 #
@@ -41,6 +43,11 @@ BACKUP DATABASE mysql_db1 to 'bup_myisam
 #
 # Inject error at Backup_restore_ctx_unlock_tables_alloc
 SET debug='d,Backup_restore_ctx_unlock_tables_alloc';
+--echo # RESTORE of a compressed MyISAM table issues two warnings:
+--echo # "Table is read only" and "Deadlock found when trying to get lock".
+--echo # This results from an internal call of FLUSH TABLES.
+--echo # RESTORE can't get back its write lock on the now compressed table.
+--echo # But it doesn't need the locks any more at this moment. So it's ok.
 --replace_column 1 #
 RESTORE FROM 'bup_myisam3.bak' OVERWRITE;
 #

=== modified file 'mysql-test/suite/backup/t/backup_myisam_sync.test'
--- a/mysql-test/suite/backup/t/backup_myisam_sync.test	2009-04-14 13:40:06 +0000
+++ b/mysql-test/suite/backup/t/backup_myisam_sync.test	2009-11-16 19:20:34 +0000
@@ -1,4 +1,7 @@
+#
 # Tests specific of MyISAM's online backup.
+# With DEBUG_SYNC.
+#
 
 --source include/not_embedded.inc
 --source include/have_debug_sync.inc
@@ -11,6 +14,7 @@
 SET DEBUG_SYNC= 'RESET';
 USE test;
 DROP DATABASE IF EXISTS mysqltest;
+let $MYSQLD_DATADIR= `select @@datadir`;
 let $MYSQLD_BACKUPDIR= `SELECT @@backupdir`;
 --error 0,1
 remove_file $MYSQLD_BACKUPDIR/bup_myisam_sync.bak;
@@ -101,10 +105,77 @@ SELECT SUM(VARIABLE_VALUE) > 0 AS key_ca
 --echo
 
 #
-# Cleanup from this test case
+# Cleanup
 #
---echo # final cleanup
+--echo # cleanup
 USE test;
 DROP DATABASE mysqltest;
 SET DEBUG_SYNC= 'RESET';
 
+--echo #
+--echo # Bug#40944 - Backup: crash after myisampack
+--echo # Patch #2
+--echo #
+CREATE DATABASE bup_myisam_sync_db1;
+CREATE TABLE bup_myisam_sync_db1.t1 (c1 VARCHAR(5), c2 int) ENGINE=MyISAM;
+CREATE INDEX i1 ON bup_myisam_sync_db1.t1 (c1, c2);
+INSERT INTO bup_myisam_sync_db1.t1 VALUES ('A',1);
+INSERT INTO bup_myisam_sync_db1.t1 SELECT * FROM bup_myisam_sync_db1.t1;
+INSERT INTO bup_myisam_sync_db1.t1 SELECT * FROM bup_myisam_sync_db1.t1;
+INSERT INTO bup_myisam_sync_db1.t1 SELECT * FROM bup_myisam_sync_db1.t1;
+INSERT INTO bup_myisam_sync_db1.t1 SELECT * FROM bup_myisam_sync_db1.t1;
+INSERT INTO bup_myisam_sync_db1.t1 SELECT * FROM bup_myisam_sync_db1.t1;
+INSERT INTO bup_myisam_sync_db1.t1 SELECT * FROM bup_myisam_sync_db1.t1;
+INSERT INTO bup_myisam_sync_db1.t1 SELECT * FROM bup_myisam_sync_db1.t1;
+FLUSH TABLE bup_myisam_sync_db1.t1;
+#CREATE TABLE bup_myisam_sync_db1.t0 LIKE bup_myisam_sync_db1.t1;
+#CREATE TABLE bup_myisam_sync_db1.t2 LIKE bup_myisam_sync_db1.t1;
+#
+--echo # exec myisampack
+--exec $MYISAMPACK -s $MYSQLD_DATADIR/bup_myisam_sync_db1/t1
+--echo # exec myisamchk
+--exec $MYISAMCHK -srq $MYSQLD_DATADIR/bup_myisam_sync_db1/t1
+#
+--replace_column 1 #
+BACKUP DATABASE bup_myisam_sync_db1 to 'bup_myisam_sync_db1.bak';
+#
+DROP DATABASE bup_myisam_sync_db1;
+#
+SET DEBUG_SYNC= 'after_restore_locks_tables SIGNAL restore_locked
+                 WAIT_FOR restore_finish';
+#SET GLOBAL debug='+O,../../log/mysqld.1.trace';
+#SET debug='+d:+t:+i';
+send RESTORE FROM 'bup_myisam_sync_db1.bak';
+#
+    --echo #
+    --echo # connection con1
+    --connect(con1, localhost, root,,)
+    SET DEBUG_SYNC= 'now WAIT_FOR restore_locked';
+    SET DEBUG_SYNC= 'wait_for_lock SIGNAL restore_finish';
+    send SELECT COUNT(*) FROM bup_myisam_sync_db1.t1 WHERE c2 < 5;
+#
+--echo #
+--echo # connection default
+--connection default
+--echo # RESTORE of a compressed MyISAM table issues two warnings:
+--echo # "Table is read only" and "Deadlock found when trying to get lock".
+--echo # This results from an internal call of FLUSH TABLES.
+--echo # RESTORE can't get back its write lock on the now compressed table.
+--echo # But it doesn't need the locks any more at this moment. So it's ok.
+--replace_column 1 ###
+reap;
+#SET debug='-d:-t:-i';
+#
+    --echo #
+    --echo # connection con1
+    --connection con1
+    reap;
+    --disconnect con1
+#
+--echo #
+--echo # connection default
+--connection default
+SET DEBUG_SYNC= 'RESET';
+DROP DATABASE bup_myisam_sync_db1;
+--remove_file $MYSQLD_BACKUPDIR/bup_myisam_sync_db1.bak
+

=== modified file 'mysql-test/suite/backup/t/backup_no_engine.test'
--- a/mysql-test/suite/backup/t/backup_no_engine.test	2009-06-18 11:28:01 +0000
+++ b/mysql-test/suite/backup/t/backup_no_engine.test	2009-11-09 10:56:12 +0000
@@ -3,6 +3,10 @@
 
 --source include/not_embedded.inc
 
+--echo Suppress this error in the server log
+call mtr.add_suppression("Can't access storage engine of table ");
+--echo
+
 # .frm file for a table using non-existent storage engine
 --let $table_def=$MYSQL_TEST_DIR/std_data/bug30938.frm
 
@@ -20,21 +24,11 @@ copy_file $table_def $MYSQLD_DATADIR/db/
 
 SHOW TABLES IN db;
 
-# backup test database, the table with no storage engine will be ignored
+# backup test database, an error will be displayed
+# as storage engine of the table is not identified
 --replace_column 1 #
+--error ER_UNKNOWN_STORAGE_ENGINE
 BACKUP DATABASE db TO "db.backup";
-
-# wipe-out backed-up database
-DROP DATABASE db;
-
---replace_column 1 #
-RESTORE FROM "db.backup";
-
-# check that the table with no engine was excluded
-SHOW TABLES IN db;
-# check that table t was correctly restored
-SHOW CREATE TABLE db.t1;	
-
+SHOW WARNINGS;
 # clean up
 DROP DATABASE db;
-remove_file $MYSQLD_BACKUPDIR/db.backup;

=== added file 'mysql-test/suite/backup/t/backup_restore_locking.test'
--- a/mysql-test/suite/backup/t/backup_restore_locking.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_restore_locking.test	2009-11-16 19:20:34 +0000
@@ -0,0 +1,201 @@
+#
+# Bug#41716 - Backup Error when sending data (for table #1)
+#             to Default/Snapshot restore driver
+#
+# Ingo Struewing, 2009-06-16, test suggested by Guilhem Bichot
+# Ingo Struewing, 2009-07-22, WL#4844
+#
+
+--source include/have_debug_sync.inc
+--source include/not_embedded.inc
+
+call mtr.add_suppression("Restore: Open and lock tables failed in RESTORE");
+
+--echo #
+--echo # Precautionary cleanup
+--echo #
+SET DEBUG_SYNC= 'RESET';
+SET @old_sessiondebug=@@session.debug;
+let $MYSQLD_BACKUPDIR=`select @@backupdir`;
+--disable_warnings
+DROP DATABASE IF EXISTS bup_reslock_db1;
+--error 0,1
+--remove_file $MYSQLD_BACKUPDIR/bup_reslock_db1.bak
+--enable_warnings
+
+--echo #
+--echo # Bug#41716 - Backup Error when sending data (for table #1)
+--echo #             to Default/Snapshot restore driver
+--echo #
+CREATE DATABASE bup_reslock_db1;
+USE bup_reslock_db1;
+CREATE TABLE t1 (c1 INT, c2 VARCHAR(100), UNIQUE(c1)) ENGINE=MEMORY;
+INSERT INTO t1 VALUES (1,"abc");
+#
+--replace_column 1 ###
+BACKUP DATABASE bup_reslock_db1 TO 'bup_reslock_db1.bak';
+#
+DROP DATABASE bup_reslock_db1;
+#
+SET DEBUG_SYNC= 'before_restore_locks_tables SIGNAL restore_before_locking
+                 WAIT_FOR restore_finish';
+send RESTORE FROM 'bup_reslock_db1.bak';
+#
+    --echo #
+    --echo # connection con1
+    --connect (con1, localhost, root,,)
+    SET DEBUG_SYNC= 'now WAIT_FOR restore_before_locking';
+    INSERT INTO bup_reslock_db1.t1 VALUES(1,"def");
+    SET DEBUG_SYNC= 'now SIGNAL restore_finish';
+    --disconnect con1
+#
+--echo #
+--echo # connection default, retrieve RESTORE result.
+--connection default
+--replace_column 1 ###
+reap;
+SET DEBUG_SYNC= 'RESET';
+#
+SELECT * FROM t1;
+FLUSH TABLE t1;
+SELECT * FROM t1;
+#
+USE test;
+DROP DATABASE bup_reslock_db1;
+--remove_file $MYSQLD_BACKUPDIR/bup_reslock_db1.bak
+
+--echo #
+--echo # WL#4844 - Implement a locking scheme for RESTORE
+--echo #
+CREATE DATABASE bup_reslock_db1;
+USE bup_reslock_db1;
+CREATE TABLE t1 (c1 INT, c2 VARCHAR(100), UNIQUE(c1)) ENGINE=MEMORY;
+INSERT INTO t1 VALUES (0,"backup");
+#
+--replace_column 1 ###
+BACKUP DATABASE bup_reslock_db1 TO 'bup_reslock_db1.bak';
+#
+DROP DATABASE bup_reslock_db1;
+#
+SET DEBUG_SYNC= 'after_restore_lock_tables_for_write
+                 SIGNAL waiting WAIT_FOR continue';
+SET DEBUG_SYNC= 'after_restore_truncate_tables
+                 SIGNAL waiting WAIT_FOR continue';
+SET DEBUG_SYNC= 'before_restore_flush_tables
+                 SIGNAL waiting WAIT_FOR continue';
+SET DEBUG_SYNC= 'before_restore_unlock_tables
+                 SIGNAL waiting WAIT_FOR continue';
+send RESTORE FROM 'bup_reslock_db1.bak';
+#
+    --echo #
+    --echo # connection con1
+    --connect (con1, localhost, root,,)
+    SET DEBUG_SYNC= 'now WAIT_FOR waiting';
+    SET DEBUG_SYNC= 'wait_for_lock SIGNAL lock_wait';
+    send INSERT INTO bup_reslock_db1.t1 VALUES(1,"after_lock_tables");
+#
+      --echo #
+      --echo # connection con2
+      --connect (con2, localhost, root,,)
+      SET DEBUG_SYNC= 'now WAIT_FOR lock_wait';
+      SET DEBUG_SYNC= 'now SIGNAL continue WAIT_FOR waiting';
+      SET DEBUG_SYNC= 'wait_for_lock SIGNAL lock_wait';
+      send INSERT INTO bup_reslock_db1.t1 VALUES(2,"after_truncate_tables");
+#
+        --echo #
+        --echo # connection con3
+        --connect (con3, localhost, root,,)
+        SET DEBUG_SYNC= 'now SIGNAL continue WAIT_FOR waiting';
+        SET DEBUG_SYNC= 'wait_for_lock SIGNAL lock_wait';
+        send INSERT INTO bup_reslock_db1.t1 VALUES(3,"before_flush_tables");
+#
+          --echo #
+          --echo # connection con4
+          --connect (con4, localhost, root,,)
+          SET DEBUG_SYNC= 'now WAIT_FOR lock_wait';
+          SET DEBUG_SYNC= 'now SIGNAL continue WAIT_FOR waiting';
+          SET DEBUG_SYNC= 'wait_for_lock SIGNAL lock_wait';
+          send INSERT INTO bup_reslock_db1.t1 VALUES(4,"before_unlock_tables");
+#
+            --echo #
+            --echo # connection con5
+            --connect (con5, localhost, root,,)
+            SET DEBUG_SYNC= 'now WAIT_FOR lock_wait';
+            SELECT state, info FROM INFORMATION_SCHEMA.PROCESSLIST;
+            SET DEBUG_SYNC= 'now SIGNAL continue';
+            --disconnect con5
+#
+--echo #
+--echo # connection default, retrieve RESTORE result
+--connection default
+--replace_column 1 ###
+reap;
+SET DEBUG_SYNC= 'RESET';
+#
+    --echo #
+    --echo # connection con1, retrieve INSERT result.
+    --connection con1
+    reap;
+    --disconnect con1
+#
+      --echo #
+      --echo # connection con2, retrieve INSERT result.
+      --connection con2
+      reap;
+      --disconnect con2
+#
+        --echo #
+        --echo # connection con3, retrieve INSERT result.
+        --connection con3
+        reap;
+        --disconnect con3
+#
+          --echo #
+          --echo # connection con4, retrieve INSERT result.
+          --connection con4
+          reap;
+          --disconnect con4
+#
+--echo #
+--echo # connection default
+--connection default
+SELECT * FROM t1 ORDER BY c1;
+FLUSH TABLE t1;
+SELECT * FROM t1 ORDER BY c1;
+#
+USE test;
+DROP DATABASE bup_reslock_db1;
+
+--echo #
+--echo # WL#4844 - Implement a locking scheme for RESTORE
+--echo # Code coverage tests.
+--echo #
+SET DEBUG='+d,error_inject_truncate_enter';
+--error ER_BACKUP_OPEN_TABLES
+RESTORE FROM 'bup_reslock_db1.bak';
+SET debug=@old_sessiondebug;
+DROP DATABASE bup_reslock_db1;
+#
+LET $ID=`SELECT CONNECTION_ID()`;
+SET DEBUG_SYNC='after_restore_truncate_tables SIGNAL sync WAIT_FOR go';
+send RESTORE FROM 'bup_reslock_db1.bak';
+#
+    --echo #
+    --echo # connection con1
+    --connect (con1, localhost, root,,)
+    SET DEBUG_SYNC= 'now WAIT_FOR sync';
+    --replace_regex /KILL QUERY [0-9]+/KILL QUERY ##/
+    eval KILL QUERY $ID;
+    SET DEBUG_SYNC= 'now SIGNAL go';
+    --disconnect con1
+#
+--echo #
+--echo # connection default, retrieve RESTORE result.
+--connection default
+--error ER_QUERY_INTERRUPTED
+reap;
+SET DEBUG_SYNC= 'RESET';
+#
+DROP DATABASE bup_reslock_db1;
+--remove_file $MYSQLD_BACKUPDIR/bup_reslock_db1.bak
+

=== modified file 'mysql-test/suite/backup_engines/r/backup_interruption.result'
--- a/mysql-test/suite/backup_engines/r/backup_interruption.result	2009-10-09 13:03:56 +0000
+++ b/mysql-test/suite/backup_engines/r/backup_interruption.result	2009-11-17 20:18:50 +0000
@@ -196,8 +196,6 @@ SHOW WARNINGS;
 Level	Code	Message
 Error	<error-code>	Query execution was interrupted
 Error	<error-code>	Query execution was interrupted
-Error	<error-code>	Query execution was interrupted
-Error	<error-code>	Query execution was interrupted
 Warning	<error-code>	Operation aborted
 #
 # Examine backup logs.
@@ -414,8 +412,6 @@ SHOW WARNINGS;
 Level	Code	Message
 Error	<error-code>	Query execution was interrupted
 Error	<error-code>	Query execution was interrupted
-Error	<error-code>	Query execution was interrupted
-Error	<error-code>	Query execution was interrupted
 Warning	<error-code>	Operation aborted
 #
 # Examine backup logs.
@@ -1412,6 +1408,7 @@ ERROR 70100: Query execution was interru
 SHOW WARNINGS;
 Level	Code	Message
 Error	<error-code>	Query execution was interrupted
+Error	<error-code>	Query execution was interrupted
 Warning	<error-code>	Operation aborted - data might be corrupted
 #
 # Examine backup logs.
@@ -1456,6 +1453,7 @@ ERROR 70100: Query execution was interru
 SHOW WARNINGS;
 Level	Code	Message
 Error	<error-code>	Query execution was interrupted
+Error	<error-code>	Query execution was interrupted
 Warning	<error-code>	Operation aborted - data might be corrupted
 #
 # Examine backup logs.
@@ -1500,6 +1498,7 @@ ERROR 70100: Query execution was interru
 SHOW WARNINGS;
 Level	Code	Message
 Error	<error-code>	Query execution was interrupted
+Error	<error-code>	Query execution was interrupted
 Warning	<error-code>	Operation aborted - data might be corrupted
 #
 # Examine backup logs.
@@ -1544,6 +1543,7 @@ ERROR 70100: Query execution was interru
 SHOW WARNINGS;
 Level	Code	Message
 Error	<error-code>	Query execution was interrupted
+Error	<error-code>	Query execution was interrupted
 Warning	<error-code>	Operation aborted - data might be corrupted
 #
 # Examine backup logs.
@@ -1588,6 +1588,7 @@ ERROR 70100: Query execution was interru
 SHOW WARNINGS;
 Level	Code	Message
 Error	<error-code>	Query execution was interrupted
+Error	<error-code>	Query execution was interrupted
 Warning	<error-code>	Operation aborted - data might be corrupted
 #
 # Examine backup logs.
@@ -1632,6 +1633,7 @@ ERROR 70100: Query execution was interru
 SHOW WARNINGS;
 Level	Code	Message
 Error	<error-code>	Query execution was interrupted
+Error	<error-code>	Query execution was interrupted
 Warning	<error-code>	Operation aborted - data might be corrupted
 #
 # Examine backup logs.
@@ -1676,6 +1678,7 @@ ERROR 70100: Query execution was interru
 SHOW WARNINGS;
 Level	Code	Message
 Error	<error-code>	Query execution was interrupted
+Error	<error-code>	Query execution was interrupted
 Warning	<error-code>	Operation aborted - data might be corrupted
 #
 # Examine backup logs.

=== modified file 'sql/backup/backup_info.cc'
--- a/sql/backup/backup_info.cc	2009-11-18 16:47:46 +0000
+++ b/sql/backup/backup_info.cc	2009-11-18 17:30:09 +0000
@@ -729,7 +729,18 @@ backup::Image_info::Db* Backup_info::add
   }
 
   // Check to see if the user can see all of the objects in the database.
-  if (obs::check_user_access(m_thd, name))
+  bool has_access= FALSE;
+  bool got_error= obs::check_user_access(m_thd, name, &has_access);
+
+  DBUG_EXECUTE_IF("ER_BACKUP_USER_PRIV_CHECK_add_db", got_error= TRUE;);
+
+  if (got_error)
+  {
+    m_log.report_error(ER_BACKUP_USER_PRIV_CHECK, m_thd->security_ctx->user);
+    return NULL;
+  }
+
+  if (!has_access)
   {
     m_log.report_error(ER_BACKUP_ACCESS_OBJS_INCOMPLETE, name->ptr());
     return NULL;
@@ -857,7 +868,18 @@ int Backup_info::add_all_dbs()
   int res= 0;
 
   // Check to see if the user can see all of the databases.
-  if (check_user_access(m_thd, 0))
+  bool has_access= FALSE;
+  bool got_error= obs::check_user_access(m_thd, 0, &has_access);
+
+  DBUG_EXECUTE_IF("ER_BACKUP_USER_PRIV_CHECK_add_all_dbs", got_error= TRUE;);
+
+  if (got_error)
+  {
+    m_log.report_error(ER_BACKUP_USER_PRIV_CHECK, m_thd->security_ctx->user);
+    return ERROR;
+  }
+
+  if (!has_access)
   {
     m_log.report_error(ER_BACKUP_ACCESS_DBS_INCOMPLETE);
     return ERROR;

=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc	2009-10-23 15:41:56 +0000
+++ b/sql/backup/kernel.cc	2009-11-17 20:18:50 +0000
@@ -249,7 +249,7 @@ execute_backup_command(THD *thd,
     /* Error condition insertion for ER_BACKUP_BACKUP_PREPARE. */
     DBUG_EXECUTE_IF("ER_BACKUP_BACKUP_PREPARE_2", res= 1;);
 
-    if (res || !info->is_valid())
+    if (context.report_killed() || res || !info->is_valid())
       DBUG_RETURN(send_error(context, ER_BACKUP_BACKUP_PREPARE));
 
     int count= info->db_count();
@@ -347,7 +347,17 @@ execute_backup_command(THD *thd,
 static
 int send_error(Backup_restore_ctx &context, int error_code, ...)
 {
-  if (!context.is_killed() && !context.error_reported())
+  using namespace backup;
+
+  /* Atmost one error should be reported. */
+  if (context.error_reported())
+    return error_code;
+  
+  /* Report error state if not already done. */
+  context.report_state(BUP_ERRORS);
+
+  /* If the query has been interrupted, do not print this message. */
+  if (!context.is_killed())
   {
     char buf[MYSQL_ERRMSG_SIZE];
     va_list args;
@@ -1097,14 +1107,26 @@ int Backup_restore_ctx::lock_tables_for_
     }
   }
 
-  DBUG_EXECUTE_IF("restore_lock_tables_for_restore",
-    /*
-       Mimic error in opening tables. Cannot be done by setting ret=1
-       after open_and_lock_tables_derived becase that method is
-       supposed to release the lock before returning error.
-    */
-    return fatal_error(report_error(ER_BACKUP_OPEN_TABLES,"RESTORE"));
-  );
+  ret= obs::lock_tables_for_write(m_thd, m_backup_tables);
+  if (ret)
+    goto err1;
+  DEBUG_SYNC(m_thd, "after_restore_lock_tables_for_write");
+
+  /*
+    Truncate tables. Some INSERT might have found the freshly
+    created table.
+  */
+  ret= obs::truncate_tables(m_thd, m_backup_tables);
+  if (ret)
+    goto err;
+  DEBUG_SYNC(m_thd, "after_restore_truncate_tables");
+
+  /*
+     Mimic error in opening tables. Cannot be done by setting ret=1
+     after open_and_lock_tables_derived becase that method is
+     supposed to release the lock before returning error.
+  */
+  DBUG_EXECUTE_IF("restore_lock_tables_for_restore", goto err;);
 
   /*
     Open and lock the tables.
@@ -1121,10 +1143,15 @@ int Backup_restore_ctx::lock_tables_for_
                                            /* Do not open tmp tables. */
                                    );
   if (ret || is_killed())
-    return fatal_error(report_error(ER_BACKUP_OPEN_TABLES,"RESTORE"));
+    goto err;
 
   m_tables_locked= TRUE;
   return 0;
+
+ err:
+  (void) obs::unlock_tables(m_thd);
+ err1:
+  return fatal_error(report_error(ER_BACKUP_OPEN_TABLES, "RESTORE"));
 }
 
 
@@ -1139,26 +1166,26 @@ void Backup_restore_ctx::unlock_tables()
     return;
 
   DBUG_PRINT("restore",("unlocking tables"));
+  close_thread_tables(m_thd);                   // Never errors.
+  m_tables_locked= FALSE;
 
   /*
     Refresh tables that have been restored. Some restore drivers might
     restore a table layout that differs from the version created by
-    materialize(). We need to force a final close after restore with
-    close_cached_tables(). Note that we do this before we unlock the
-    tables. Otherwise other threads could use the still open tables
-    before we refresh them.
+    materialize(). We need to force a final close after restore.
 
     For information about a concrete problem, see the comment in
     myisam_backup_engine.cc:Table_restore::close().
 
     Use the restore table list as created by lock_tables_for_restore().
-  */
-  if (m_backup_tables)
-    close_cached_tables(m_thd, m_backup_tables, FALSE, FALSE);
-
-  close_thread_tables(m_thd);                   // Never errors.
-  m_tables_locked= FALSE;
 
+    We ignore the status from FLUSH and UNLOCK as there is no way
+    to deal with such problems here.
+  */
+  DEBUG_SYNC(m_thd, "before_restore_flush_tables");
+  (void) obs::flush_tables(m_thd, m_backup_tables);
+  DEBUG_SYNC(m_thd, "before_restore_unlock_tables");
+  (void) obs::unlock_tables(m_thd);
   return;
 }
 

=== modified file 'sql/backup/logger.h'
--- a/sql/backup/logger.h	2009-10-21 13:32:24 +0000
+++ b/sql/backup/logger.h	2009-11-17 20:18:50 +0000
@@ -263,7 +263,7 @@ void Logger::report_start(time_t when)
   report_error(log_level::INFO, m_type == BACKUP ? ER_BACKUP_BACKUP_START
                                                  : ER_BACKUP_RESTORE_START);
   backup_log->start(when);
-  backup_log->state(BUP_RUNNING);
+  backup_log->set_state(BUP_RUNNING);
 }
 
 
@@ -329,21 +329,23 @@ void Logger::report_aborted(time_t when,
 
 
 /**
-  Report change of the state of operation
+  Report current state of operation only when there is state change.
+  This can be called multiple times without generating duplicate messages.
 
   For possible states see definition of @c enum_backup_state
 
   @todo Consider reporting state changes in the server error log (as info
   entries).
+
 */
 
 inline
 void Logger::report_state(enum_backup_state state)
 {
-  DBUG_ASSERT(m_state == RUNNING || m_state == READY);
-  DBUG_ASSERT(backup_log);
-
-  backup_log->state(state);
+  if (!backup_log)
+    return;
+  if (backup_log->get_state() != state)
+    backup_log->set_state(state);
 }
 
 
@@ -443,7 +445,7 @@ int Logger::init(enum_type type, const c
 
   m_type= type;
   backup_log = new Backup_log(m_thd, (enum_backup_operation)type, query);
-  backup_log->state(BUP_STARTING);
+  backup_log->set_state(BUP_STARTING);
   m_state= READY;
   DEBUG_SYNC(m_thd, "after_backup_log_init");
   return 0;

=== modified file 'sql/backup/stream_v1_transport.c'
--- a/sql/backup/stream_v1_transport.c	2009-10-22 08:08:43 +0000
+++ b/sql/backup/stream_v1_transport.c	2009-11-16 07:36:42 +0000
@@ -2022,7 +2022,7 @@ int bstream_next_chunk(backup_stream *s)
         empty the buffer so that the next fragment will be loaded into it when
         the buffer is re-filled below.
       */
-      if (s->buf.header < s->buf.pos)
+      if (s->buf.header <= s->buf.pos)
         s->buf.begin= s->buf.header;
       else
       {

=== modified file 'sql/log.cc'
--- a/sql/log.cc	2009-10-26 14:02:26 +0000
+++ b/sql/log.cc	2009-11-16 18:37:18 +0000
@@ -3936,10 +3936,73 @@ bool MYSQL_BACKUP_LOG::write(THD *thd, s
       goto err;
     if (write_str(history_data->binlog_file))
       goto err;
-    if (write_int(history_data->state))
+
+    /*
+      Print the enumerated values to match the columns in the
+      table.
+    */
+    switch (history_data->state) {
+    case BUP_COMPLETE:
+      {
+        if (write_str("complete"))
+          goto err;
+        break;
+      }
+    case BUP_STARTING:
+      {
+        if (write_str("starting"))
+          goto err;
+        break;
+      }
+    case BUP_VALIDITY_POINT:
+      {
+        if (write_str("validity point"))
+          goto err;
+        break;
+      }
+    case BUP_RUNNING:
+      {
+        if (write_str("running"))
+          goto err;
+        break;
+      }
+    case BUP_ERRORS:
+      {
+        if (write_str("error"))
+          goto err;
+        break;
+      }
+    case BUP_CANCEL:
+      {
+        if (write_str("cancel"))
+          goto err;
+        break;
+      }
+    default:   // Should be no other values.
       goto err;
-    if (write_int(history_data->operation))
+    }
+      
+    /*
+      Print the enumerated values to match the columns in the
+      table.
+    */
+    switch (history_data->operation) {
+    case OP_BACKUP:
+      {
+        if (write_str("backup"))
+          goto err;
+        break;
+      }
+    case OP_RESTORE:
+      {
+        if (write_str("restore"))
+          goto err;
+        break;
+      }
+    default:   // Should be no other values.
       goto err;
+    }
+    
     if (write_int(history_data->error_num))
       goto err;
     if (write_int(history_data->num_objects))

=== modified file 'sql/share/errmsg-utf8.txt'
--- a/sql/share/errmsg-utf8.txt	2009-10-12 09:08:34 +0000
+++ b/sql/share/errmsg-utf8.txt	2009-11-17 20:18:50 +0000
@@ -6562,3 +6562,5 @@ ER_BACKUP_ACCESS_OBJS_INCOMPLETE
   eng "Insufficient privileges. You do not have privileges to backup database '%s'."
 ER_WARN_I_S_SKIPPED_TABLE
   eng "Table '%s'.'%s' was skipped since its definition is being modified by concurrent DDL statement."
+ER_BACKUP_USER_PRIV_CHECK
+  eng "Failed to perform access privileges check for user '%s'."

=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt	2009-10-26 14:02:26 +0000
+++ b/sql/share/errmsg.txt	2009-11-17 20:18:50 +0000
@@ -6562,3 +6562,5 @@ ER_BACKUP_ACCESS_OBJS_INCOMPLETE
   eng "Insufficient privileges. You do not have privileges to backup database '%s'."
 ER_WARN_I_S_SKIPPED_TABLE
   eng "Table '%s'.'%s' was skipped since its definition is being modified by concurrent DDL statement."
+ER_BACKUP_USER_PRIV_CHECK
+  eng "Failed to perform access privileges check for user '%s'."

=== modified file 'sql/si_logs.cc'
--- a/sql/si_logs.cc	2009-05-21 13:17:37 +0000
+++ b/sql/si_logs.cc	2009-11-17 20:18:50 +0000
@@ -162,13 +162,24 @@ bool Backup_log::write_master_binlog_inf
   @todo Consider reporting state changes in the server error log (as info
   entries).
  */
-void Backup_log::state(enum_backup_state state)
+void Backup_log::set_state(enum_backup_state state)
 {
   m_op_hist.state= state;
   logger.backup_progress_log_write(m_thd, m_op_hist.backup_id, "backup kernel", 0, 
                             0, 0, 0, 0, get_state_string(state));
 }
 
+/** 
+  Get current state of operation.
+ 
+  For possible states see definition of @c enum_backup_state 
+ */
+enum_backup_state Backup_log::get_state()
+{
+  return m_op_hist.state;
+}
+
+
 /**
   Report validity point creation time.
 

=== modified file 'sql/si_logs.h'
--- a/sql/si_logs.h	2009-05-21 13:17:37 +0000
+++ b/sql/si_logs.h	2009-11-17 20:18:50 +0000
@@ -10,27 +10,30 @@
 
 /**
   List of operations for backup history log.
+  
+  @note These must match the definition for the column 'operation'
+  in the backup_history and backup_progress tables.
 */
 enum enum_backup_operation
 {
   OP_BACKUP = 1,
-  OP_RESTORE,
-  OP_SHOW,
-  OP_OTHER
+  OP_RESTORE = 2
 };
 
 /**
   List of states for backup logs.
+  
+  @note These must match the definition for the column 'backup_state'
+  in the backup_history table.
 */
 enum enum_backup_state
 {
-  BUP_UNKNOWN = 0,
-  BUP_COMPLETE,
-  BUP_STARTING,
-  BUP_VALIDITY_POINT,
-  BUP_RUNNING,
-  BUP_ERRORS,
-  BUP_CANCEL
+  BUP_COMPLETE = 1,
+  BUP_STARTING = 2,
+  BUP_VALIDITY_POINT = 3,
+  BUP_RUNNING = 4,
+  BUP_ERRORS = 5,
+  BUP_CANCEL = 6
 };
 
 /**
@@ -130,7 +133,8 @@ public:
     the backup_history log.
   */
   ulonglong get_backup_id() { return m_op_hist.backup_id; }
-  void state(enum_backup_state);
+  void set_state(enum_backup_state);
+  enum_backup_state get_state();
   void error_num(int code) { m_op_hist.error_num= code; }
   void binlog_start_pos(unsigned long int pos) 
   { 

=== modified file 'sql/si_objects.cc'
--- a/sql/si_objects.cc	2009-11-04 14:18:21 +0000
+++ b/sql/si_objects.cc	2009-11-18 15:27:51 +0000
@@ -180,22 +180,18 @@ void Si_session_context::restore_si_ctx(
 ///////////////////////////////////////////////////////////////////////////
 
 /**
-  Execute one DML statement in a backup-specific context. Result set and
-  warning information are stored in the output parameter. Some session
-  attributes are preserved and reset to predefined values before query
-  execution (@see Si_session_context).
- 
-  @note This method will temporarily invoke additional privileges for 
-  all SELECT or SHOW CREATE statements.
+  Execute one SQL statement in a backup-specific context.
 
-  @param[in]  thd         Thread context.
-  @param[in]  query       SQL query to be executed.
-  @param[in]  get_warnings    If true, copy warnings to the error stack
-  @param[out] ed_connection   A place to store result and warnings.
+  Some session attributes are preserved and reset to predefined values
+  before query execution (@see Si_session_context).
 
-  @return Error status.
-    @retval TRUE on error.
-    @retval FALSE on success.
+  @param[in]    thd             thread handle
+  @param[in]    ed_connection   Ed_connection handle
+  @param[in]    query           SQL query to be executed
+
+  @return       status
+    @retval     TRUE            error
+    @retval     FALSE           success
 */
 
 bool
@@ -1310,11 +1306,6 @@ Iterator *create_row_set_iterator(THD *t
   if (run_service_interface_sql(thd, &ed_connection, query, TRUE))
     /* Query failed with an error */
     return NULL;
-  else if(ed_connection.get_warn_count())
-    /* Push warnings to BACKUP's error stack. Calling method will
-       decide if the warnings are a problem later when serializing the
-       object. */
-    thd->warning_info->append_warnings(thd, ed_connection.get_warn_list());
 
   DBUG_ASSERT(ed_connection.get_field_count());
 
@@ -2561,9 +2552,9 @@ Obj_iterator *get_databases(THD *thd)
 
   @param[in] THD     Current thread
   
-  @return uint Number of databases.
+  @return int Number of databases. Return value of -1 indicates failure.
 */
-uint get_num_dbs(THD *thd)
+int get_num_dbs(THD *thd)
 {
   Ed_connection ed_connection(thd);
   Ed_result_set *ed_result_set;
@@ -2578,10 +2569,7 @@ uint get_num_dbs(THD *thd)
   if (run_service_interface_sql(thd, &ed_connection,
 				s_stream.lex_string(), TRUE))
     /* Query failed with an error */
-    return NULL;
-  else if(ed_connection.get_warn_count())
-    /* Push warnings to BACKUP's error stack. */
-    thd->warning_info->append_warnings(thd, ed_connection.get_warn_list());
+    return -1;
 
   DBUG_ASSERT(ed_connection.get_field_count());
 
@@ -2607,9 +2595,9 @@ uint get_num_dbs(THD *thd)
   @param[in] THD     Current thread
   @param[in] String  Database name.
 
-  @return uint Number of objects in the database.
+  @return int Number of objects in the database. Value of -1 means failure.
 */
-uint get_num_objects(THD *thd, const String *db_name)
+int get_num_objects(THD *thd, const String *db_name)
 {
   Ed_connection ed_connection(thd);
   Ed_result_set *ed_result_set;
@@ -2635,10 +2623,7 @@ uint get_num_objects(THD *thd, const Str
   if (run_service_interface_sql(thd, &ed_connection, 
 				s_stream.lex_string(), TRUE))
     /* Query failed with an error */
-    return NULL;
-  else if(ed_connection.get_warn_count())
-    /* Push warnings to BACKUP's error stack. */
-    thd->warning_info->append_warnings(thd, ed_connection.get_warn_list());
+    return -1;
 
   DBUG_ASSERT(ed_connection.get_field_count());
 
@@ -2650,10 +2635,13 @@ uint get_num_objects(THD *thd, const Str
 }
 
 ///////////////////////////////////////////////////////////////////////////
-bool check_user_access(THD *thd, const String *db_name)
+bool check_user_access(THD *thd, const String *db_name, bool *has_access)
 {
-  uint elev_count;
-  uint user_count;
+  int elev_count;
+  int user_count;
+
+  DBUG_ASSERT(has_access);
+  *has_access= false;                           /* Reset access status. */
 
   /*
     Get value from user context without elevation.
@@ -2663,6 +2651,9 @@ bool check_user_access(THD *thd, const S
   else 
     user_count= get_num_objects(thd, db_name);
 
+  if (user_count < 0)
+    return TRUE;                                /* Return error status */
+
   /* 
     Peform global elevation with SELECT to get value of
     someone with global SELECT (e.g. root).
@@ -2682,22 +2673,41 @@ bool check_user_access(THD *thd, const S
   thd->security_ctx->master_access= saved_master_access; 
   thd->security_ctx->db_access= saved_db_access; 
 
-  /*
-    Compare results and return.
-  */
-  return !(user_count == elev_count);
+  if (elev_count < 0)
+    return TRUE;                                /* Return error status */
+
+  /* User has proper access if both counts are same. */
+  *has_access= (user_count == elev_count);
+
+  return FALSE;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 Obj_iterator *get_db_tables(THD *thd, const String *db_name)
 {
   String_stream s_stream;
+  /*
+    BUG#45587: Backup of tables using a non-existent storage engine
+               does not give warning/error 
+    BUG#47697: Inconsistencies in the query outputs on
+               INFORMATION_SCHEMA.TABLES 
+
+    Once BUG#47697 is fixed, the query s_stream  should be reverted 
+    to following query:
+    s_stream<<
+      "SELECT '" << db_name << "', table_name "
+      "FROM INFORMATION_SCHEMA.TABLES "
+      "WHERE table_schema = '" << db_name << "' AND "
+      "table_type = 'BASE TABLE'";
+   */
 
   s_stream <<
-    "SELECT '" << db_name << "', table_name "
+    "SELECT '" << db_name << "', table_name " 
+    "FROM ( SELECT * "
     "FROM INFORMATION_SCHEMA.TABLES "
     "WHERE table_schema = '" << db_name << "' AND "
-    "table_type = 'BASE TABLE'";
+    "table_type = 'BASE TABLE'"
+    ") AS get_table";
 
   return create_row_set_iterator<Db_tables_iterator>(thd, s_stream.lex_string());
 }
@@ -2735,9 +2745,15 @@ Obj_iterator *get_db_stored_procedures(T
   String_stream s_stream;
   s_stream <<
     "SELECT '" << db_name << "', routine_name "
-    "FROM INFORMATION_SCHEMA.ROUTINES "
-    "WHERE routine_schema COLLATE utf8_bin = '" << db_name << "' AND "
-    "routine_type = 'PROCEDURE'";
+    "FROM INFORMATION_SCHEMA.ROUTINES ";
+  /*
+    We need to use case insensitive compare when LCTN = 2 and on Windows. 
+  */
+  if ((lower_case_table_names == 2) && IF_WIN(1,0))
+    s_stream << "WHERE routine_schema COLLATE utf8_general_ci = '" << db_name;
+  else
+    s_stream << "WHERE routine_schema COLLATE utf8_bin = '" << db_name;
+  s_stream << "' AND routine_type = 'PROCEDURE'";
 
   return create_row_set_iterator<Db_stored_proc_iterator>(thd, s_stream.lex_string());
 }
@@ -2749,9 +2765,15 @@ Obj_iterator *get_db_stored_functions(TH
   String_stream s_stream;
   s_stream <<
     "SELECT '" << db_name << "', routine_name "
-    "FROM INFORMATION_SCHEMA.ROUTINES "
-    "WHERE routine_schema COLLATE utf8_bin = '" << db_name <<"' AND "
-    "routine_type = 'FUNCTION'";
+    "FROM INFORMATION_SCHEMA.ROUTINES ";
+  /*
+    We need to use case insensitive compare when LCTN = 2 and on Windows. 
+  */
+  if ((lower_case_table_names == 2) && IF_WIN(1,0))
+    s_stream << "WHERE routine_schema COLLATE utf8_general_ci = '" << db_name;
+  else
+    s_stream << "WHERE routine_schema COLLATE utf8_bin = '" << db_name;
+  s_stream << "' AND routine_type = 'FUNCTION'";
 
   return create_row_set_iterator<Db_stored_func_iterator>(thd, s_stream.lex_string());
 }
@@ -2764,8 +2786,14 @@ Obj_iterator *get_db_events(THD *thd, co
   String_stream s_stream;
   s_stream <<
     "SELECT '" << db_name << "', event_name "
-    "FROM INFORMATION_SCHEMA.EVENTS "
-    "WHERE event_schema COLLATE utf8_bin = '" << db_name <<"'";
+    "FROM INFORMATION_SCHEMA.EVENTS ";
+  /*
+    We need to use case insensitive compare when LCTN = 2 and on Windows. 
+  */
+  if ((lower_case_table_names == 2) && IF_WIN(1,0))
+    s_stream << "WHERE event_schema COLLATE utf8_general_ci = '" << db_name << "'";
+  else
+    s_stream << "WHERE event_schema COLLATE utf8_bin = '" << db_name <<"'";
 
   return create_row_set_iterator<Db_event_iterator>(thd, s_stream.lex_string());
 #else
@@ -3399,6 +3427,150 @@ int Name_locker::release_name_locks()
 ///////////////////////////////////////////////////////////////////////////
 
 //
+// Miscellaneous.
+//
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+   Acquire locks on a list of tables.
+
+   @param[in]   thd             current thread
+   @param[in]   table_list      list of tables to lock for write
+
+   @return      status
+     @retval    FALSE           success
+     @retval    TRUE            error
+*/
+
+bool lock_tables_for_write(THD *thd, TABLE_LIST *table_list)
+{
+  Ed_connection ed_connection(thd);
+  String_stream s_stream;
+  TABLE_LIST *tlist;
+  bool error_status= FALSE;
+  DBUG_ENTER("obs:lock_tables_for_write");
+
+  if (table_list)
+  {
+    s_stream << "LOCK TABLE ";
+    for (tlist= table_list; tlist; tlist= tlist->next_global)
+    {
+      if (tlist != table_list)
+        s_stream << ", ";
+      s_stream << "`" << tlist->db << "`.`" << tlist->table_name << "` WRITE";
+    }
+
+    error_status= run_service_interface_sql(thd, &ed_connection,
+                                            s_stream.lex_string(), TRUE);
+  }
+  DBUG_RETURN(error_status);
+}
+
+
+/**
+   Release all table locks of this thread.
+
+   @param[in]   thd             current thread
+
+   @return      status
+     @retval    FALSE           success
+     @retval    TRUE            error
+*/
+
+bool unlock_tables(THD *thd)
+{
+  Ed_connection ed_connection(thd);
+  String_stream s_stream;
+  bool error_status;
+  DBUG_ENTER("obs:unlock_tables");
+
+  s_stream << "UNLOCK TABLES";
+  error_status= run_service_interface_sql(thd, &ed_connection,
+                                          s_stream.lex_string(), TRUE);
+  DBUG_RETURN(error_status);
+}
+
+
+/**
+   Flush a list of tables.
+
+   @param[in]   thd             current thread
+   @param[in]   table_list      list of tables to flush
+
+   @return      status
+     @retval    FALSE           success
+     @retval    TRUE            error
+*/
+
+bool flush_tables(THD *thd, TABLE_LIST *table_list)
+{
+  Ed_connection ed_connection(thd);
+  String_stream s_stream;
+  TABLE_LIST *tlist;
+  bool error_status= FALSE;
+  DBUG_ENTER("obs:flush_tables");
+
+  for (tlist= table_list; tlist; tlist= tlist->next_global)
+  {
+    s_stream.reset();
+    s_stream << "FLUSH TABLE ";
+    s_stream << "`" << tlist->db << "`.`" << tlist->table_name << "`";
+    if (run_service_interface_sql(thd, &ed_connection,
+                                  s_stream.lex_string(), TRUE))
+    {
+      error_status= TRUE;
+      DBUG_PRINT("error", ("execute direct: '%s'  errno: %d",
+                           s_stream.lex_string()->str,
+                           ed_connection.get_last_errno()));
+    }
+  }
+
+  DBUG_RETURN(error_status);
+}
+
+
+/**
+   Truncate a list of tables.
+
+   @param[in]   thd             current thread
+   @param[in]   table_list      list of tables to truncate
+
+   @return      status
+     @retval    FALSE           success
+     @retval    TRUE            error
+*/
+
+bool truncate_tables(THD *thd, TABLE_LIST *table_list)
+{
+  Ed_connection ed_connection(thd);
+  String_stream s_stream;
+  TABLE_LIST *tlist;
+  DBUG_ENTER("obs:truncate_tables");
+
+  /* Allow to execute DDL operations. */
+  ::obs::bml_exception_on(thd);
+
+  for (tlist= table_list; tlist; tlist= tlist->next_global)
+  {
+    s_stream.reset();
+    s_stream << "TRUNCATE TABLE ";
+    s_stream << "`" << tlist->db << "`.`" << tlist->table_name << "`";
+    if (run_service_interface_sql(thd, &ed_connection,
+                                  s_stream.lex_string(), TRUE))
+      DBUG_RETURN(TRUE);
+  }
+
+  /* Disable further DDL execution. */
+  ::obs::bml_exception_off(thd);
+
+  DBUG_RETURN(FALSE);
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+//
 // Implementation: Replication methods.
 //
 

=== modified file 'sql/si_objects.h'
--- a/sql/si_objects.h	2009-11-04 14:18:21 +0000
+++ b/sql/si_objects.h	2009-11-17 20:18:50 +0000
@@ -185,18 +185,17 @@ Obj_iterator *get_databases(THD *thd);
   2) If db_name != 0, the method shall check the user's visibility for all
      objects in the database specified. 
  
-  @param[in] THD     The current thread.
-  @param[in] String  The database name to check or 0
-
-  @returns Information whether user can see all specified objects
-    @retval TRUE
-      if db_name != 0 : user does not have visibility to the database specified
-      if db_name == 0 : user does not have visibility to all databases
-    @retval FALSE
-      if db_name != 0 : user does have visibility to the database specified
-      if db_name == 0 : user does have visibility to all databases
+  @param[in]  THD     the current thread
+  @param[in]  String  the database name to check
+  @param[out] bool    set to true/false as described below:
+                      TRUE  : User has the required access permission
+                      FALSE : User does not have the required access permission
+
+  @return boolean value which indicates if an error has occured.
+    @retval TRUE indicates error
+    @retval FALSE indicates success
 */
-bool check_user_access(THD *thd, const String *db_name);
+bool check_user_access(THD *thd, const String *db_name, bool *has_access);
 
 /**
   Create an iterator over all base tables in a particular database.
@@ -513,6 +512,20 @@ private:
 ///////////////////////////////////////////////////////////////////////////
 
 //
+// Miscellaneous.
+//
+
+///////////////////////////////////////////////////////////////////////////
+
+bool lock_tables_for_write(THD *thd, TABLE_LIST *table_list);
+bool unlock_tables(THD *thd);
+bool flush_tables(THD *thd, TABLE_LIST *table_list);
+bool truncate_tables(THD *thd, TABLE_LIST *table_list);
+
+
+///////////////////////////////////////////////////////////////////////////
+
+//
 // Replication methods.
 //
 

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2009-10-25 13:41:27 +0000
+++ b/sql/sql_base.cc	2009-11-17 15:17:00 +0000
@@ -1073,7 +1073,8 @@ err_with_reopen:
       old locks. This should always succeed (unless some external process
       has removed the tables)
     */
-    thd->locked_tables_list.reopen_tables(thd);
+    if (thd->locked_tables_list.reopen_tables(thd))
+      result= TRUE;
     /*
       Since downgrade_exclusive_lock() won't do anything with shared
       metadata lock it is much simpler to go through all open tables rather

=== modified file 'sql/sql_delete.cc'
--- a/sql/sql_delete.cc	2009-10-23 06:24:37 +0000
+++ b/sql/sql_delete.cc	2009-11-16 19:20:34 +0000
@@ -1129,6 +1129,10 @@ bool mysql_truncate(THD *thd, TABLE_LIST
   Ha_global_schema_lock_guard global_schema_lock_guard(thd);
   DBUG_ENTER("mysql_truncate");
 
+  DBUG_EXECUTE_IF("error_inject_truncate_enter",
+                  my_error(ER_UNKNOWN_ERROR, MYF(0));
+                  DBUG_RETURN(TRUE););
+
   mysql_ha_rm_tables(thd, table_list);
 
   bzero((char*) &create_info,sizeof(create_info));

=== modified file 'unittest/backup/bstr_callback_errors-t.c'
--- a/unittest/backup/bstr_callback_errors-t.c	2009-10-23 06:24:37 +0000
+++ b/unittest/backup/bstr_callback_errors-t.c	2009-11-16 07:36:42 +0000
@@ -30,14 +30,21 @@ void run_test()
 {
   uint i;
   uint planned;
+  uint read_planned, write_planned;
+  
+  write_planned= 1 + global_count + 4 + db_count
+                   + 1 + global_count + perdb_count;
+ 
+  read_planned= 3 + global_count + perdb_count + 2;
+
+  planned = read_planned+write_planned;
+
+  plan(planned);
 
   init_catalog(&img_header);
 
   diag("Testing callback failures during writing of backup image");
 
-  planned= 1 + global_count + 4 + db_count
-           + 1 + global_count + perdb_count + 1;
-
   /*
     Do a clean write of backup image to fill callback_counts structure holding
     counters for callback functions.
@@ -89,7 +96,6 @@ void run_test()
 
   diag("Testing callback failures during reading of backup image");
 
-  planned+= 3 + global_count + perdb_count + 2;
 
   /* Do a clean read of the backup image to set the callback counters. */
   reset_counts();
@@ -124,8 +130,6 @@ void run_test()
   /* test errors in memory allocation */
   ok(fail_alloc(RD), "Errors in memory allocation");
 
-  /* Plan (1..n) must be at the beginning or end of the TAP output. */
-  plan(planned);
 }
 
 

=== modified file 'unittest/backup/bstr_eos-t.c'
--- a/unittest/backup/bstr_eos-t.c	2009-10-12 09:08:34 +0000
+++ b/unittest/backup/bstr_eos-t.c	2009-11-16 07:36:42 +0000
@@ -60,6 +60,10 @@ void run_test()
   image_header  hdr;
   int  i;
   byte header;
+ /*
+   Number of tests to be planned are not known at this point.
+ */
+  plan(NO_PLAN);
 
   init_catalog(&hdr);
 
@@ -135,8 +139,6 @@ void run_test()
     *chunk[i]= header;
   }
 
-  /* Plan (1..n) must be at the beginning or end of the TAP output. */
-  plan(1 + 2*chunk_count + 3*(chunk_count-3));
 }
 
 

=== modified file 'unittest/backup/bstr_io_errors-t.c'
--- a/unittest/backup/bstr_io_errors-t.c	2009-10-12 09:08:34 +0000
+++ b/unittest/backup/bstr_io_errors-t.c	2009-11-16 07:36:42 +0000
@@ -16,7 +16,11 @@ void run_test()
 {
   int i;
   int  can_pass;
-  uint planned;
+  
+  /*
+    Number of tests to be planned are not known at this point.
+  */
+  plan(NO_PLAN);
 
   init_catalog(&img_header);
 
@@ -29,7 +33,6 @@ void run_test()
   diag("Made %lu write calls", io_counts.write);
   diag("Wrote %lu bytes", (long unsigned)io_counts.write_bytes);
 
-  planned= 1 + 2*io_counts.write;
 
   /*
     Errors during last 2 write calls (which happen during closing of a stream)
@@ -61,7 +64,6 @@ void run_test()
   diag("Made %lu read calls", io_counts.read);
   diag("Read %lu bytes", (long unsigned)io_counts.read_bytes);
 
-  planned+= 1 + io_counts.read;
 
   for(i= io_counts.read; i > 0 ; --i)
   {
@@ -71,7 +73,4 @@ void run_test()
        "Failing %d-th read call", i);
   }
 
-  /* Plan (1..n) must be at the beginning or end of the TAP output. */
-  plan(planned);
 }
-

=== modified file 'unittest/backup/bstr_random_chunks-t.c'
--- a/unittest/backup/bstr_random_chunks-t.c	2009-10-12 09:08:34 +0000
+++ b/unittest/backup/bstr_random_chunks-t.c	2009-11-16 07:36:42 +0000
@@ -44,9 +44,12 @@ void run_test()
   size_t byte_count;
   size_t csize;
   int    ret;
-  uint   planned;
 
   stream_block_size= BSIZE;
+ /*
+   Number of tests to be planned are not known at this point.
+  */
+  plan(NO_PLAN);
 
   diag("Writing");
 
@@ -79,7 +82,6 @@ void run_test()
 
   diag("Reading");
 
-  planned= 2*chunk_count + 2;
 
   ret= backup_stream_open_rd(&stream, "random.bst"); 
   if (ret)
@@ -111,8 +113,6 @@ void run_test()
   ok(BSTREAM_EOS == ret,"Moving to next chunk after EOS was hit");
 
  end:
-  /* Plan (1..n) must be at the beginning or end of the TAP output. */
-  plan(planned);
 
   backup_stream_close(&stream);
 }


Attachment: [text/bzr-bundle] bzr/charles.bell@sun.com-20091118173009-vhsciy2p1b9q0wni.bundle
Thread
bzr commit into mysql-6.0-backup branch (charles.bell:2889) Bug#47879Chuck Bell18 Nov