#At file:///home/cbell/source/bzr/mysql-6.0-backup-merge/
2671 Chuck Bell 2008-08-11 [merge]
Merge backup -> backup-merge
removed:
mysql-test/r/backup_view_on_view.result
mysql-test/t/backup_view_on_view.test
added:
mysql-test/r/backup_backupdir.result
mysql-test/r/backup_concurrent.result
mysql-test/t/backup_backupdir.test
mysql-test/t/backup_concurrent.test
modified:
mysql-test/lib/mtr_cases.pl
mysql-test/lib/mtr_report.pl
mysql-test/r/backup_progress.result
mysql-test/r/backup_views.result
mysql-test/t/backup_progress.test
mysql-test/t/backup_views.test
mysql-test/t/disabled.def
scripts/mysql_system_tables.sql
sql/backup/backup_aux.h
sql/backup/backup_info.cc
sql/backup/backup_kernel.h
sql/backup/data_backup.cc
sql/backup/image_info.cc
sql/backup/image_info.h
sql/backup/kernel.cc
sql/backup/stream.cc
sql/backup/stream.h
sql/backup/stream_v1.c
sql/mysqld.cc
sql/set_var.cc
sql/set_var.h
sql/share/errmsg.txt
sql/si_objects.cc
sql/sql_parse.cc
storage/myisam/mi_dynrec.c
storage/myisam/mi_examine_log.c
storage/myisam/mi_locking.c
storage/myisam/mi_open.c
storage/myisam/myisam_backup_engine.cc
storage/myisam/myisamdef.h
=== modified file 'mysql-test/lib/mtr_cases.pl'
--- a/mysql-test/lib/mtr_cases.pl 2008-06-30 20:21:41 +0000
+++ b/mysql-test/lib/mtr_cases.pl 2008-08-05 22:45:51 +0000
@@ -490,6 +490,37 @@ sub optimize_cases {
# Save binlog format for dynamic switching
$tinfo->{binlog_format}= $test_binlog_format;
}
+
+ # =======================================================
+ # Check that engine selected by
+ # --default-storage-engine=<engine> is supported
+ # =======================================================
+ my %builtin_engines = ('myisam' => 1, 'memory' => 1);
+
+ foreach my $opt ( @{$tinfo->{master_opt}} ) {
+ my $default_engine=
+ mtr_match_prefix($opt, "--default-storage-engine=");
+
+ if (defined $default_engine){
+
+
+ my $engine_value= $::mysqld_variables{$default_engine};
+
+ if ( ! exists $::mysqld_variables{$default_engine} and
+ ! exists $builtin_engines{$default_engine} )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}=
+ "'$default_engine' not supported";
+ }
+
+ $tinfo->{'ndb_test'}= 1
+ if ( $default_engine =~ /^ndb/i );
+ $tinfo->{'innodb_test'}= 1
+ if ( $default_engine =~ /^innodb/i );
+ }
+ }
+
}
}
=== modified file 'mysql-test/lib/mtr_report.pl'
--- a/mysql-test/lib/mtr_report.pl 2008-07-09 07:12:43 +0000
+++ b/mysql-test/lib/mtr_report.pl 2008-08-11 10:41:41 +0000
@@ -333,6 +333,18 @@ sub mtr_report_stats ($) {
(
/Backup:/ or /Restore:/ or /Can't open the online backup progress tables/
) or
+
+ # backup_backupdir test is supposed to trigger backup related errors
+ ($testname eq 'main.backup_backupdir') and
+ (
+ /Backup:/ or /Can't write to backup location/
+ ) or
+
+ # backup_concurrent performs a backup that should fail
+ ($testname eq 'main.backup_concurrent') and
+ (
+ /Can't execute this command because another BACKUP\/RESTORE operation is in progress/
+ ) or
# The tablespace test triggers error below on purpose
($testname eq 'main.backup_tablespace') and
@@ -340,6 +352,14 @@ sub mtr_report_stats ($) {
/Restore: Tablespace .* needed by tables being restored has changed on the server/
) or
+ # The views test triggers errors below on purpose
+ ($testname eq 'main.backup_views') and
+ (
+ /Backup: Failed to add view/ or
+ /Backup: Failed to obtain meta-data for view/ or
+ /Restore: Could not restore view/
+ ) or
+
# ignore warning generated when backup engine selection algorithm is tested
($testname eq 'main.backup_no_be') and /Backup: Cannot create backup engine/ or
# ignore warnings generated when backup privilege is tested
=== added file 'mysql-test/r/backup_backupdir.result'
--- a/mysql-test/r/backup_backupdir.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/backup_backupdir.result 2008-08-08 17:21:31 +0000
@@ -0,0 +1,56 @@
+Reset backupdir
+SET @@global.backupdir = @@global.datadir;
+DROP DATABASE IF EXISTS bup_backupdir;
+Create a database
+CREATE DATABASE bup_backupdir;
+CREATE TABLE bup_backupdir.t1(a INT);
+INSERT INTO bup_backupdir.t1 VALUES (1), (2), (3);
+Create a directory for backup images
+Reset backupdir
+SET @@global.backupdir = '../tmp/backup';
+Perform backup
+BACKUP DATABASE bup_backupdir TO 'bup_backupdir1.bak';
+backup_id
+#
+Ensure backup image file went to the correct location
+/backup/bup_backupdir.bak
+Perform restore
+RESTORE FROM 'bup_backupdir1.bak';
+backup_id
+#
+Now do the backup and restore by specifying a path.
+Perform backup
+BACKUP DATABASE bup_backupdir TO '../bup_backupdir2.bak';
+backup_id
+#
+Ensure backup image file went to the correct location
+Perform restore
+RESTORE FROM '../bup_backupdir2.bak';
+backup_id
+#
+Perform backup
+BACKUP DATABASE bup_backupdir TO '../../bup_backupdir3.bak';
+backup_id
+#
+Ensure backup image file went to the correct location
+Reset backupdir with ending /
+SET @@global.backupdir = '../tmp/backup/';
+Perform backup
+BACKUP DATABASE bup_backupdir TO '../../bup_backupdir4.bak';
+backup_id
+#
+Ensure backup image file went to the correct location
+Try a backup to an invalid relative path.
+BACKUP DATABASE bup_backupdir TO '../../../../../../../../../../../../../../../../../../bup_backupdir5.bak';
+ERROR HY000: Can't write to backup location '../../../../../../../../../../../../../../../../../../bup_backup' (file already exists?)
+Try a backup to an invalid hard path.
+BACKUP DATABASE bup_backupdir TO '/dev/not/there/either/bup_backupdir6.bak';
+ERROR HY000: Can't write to backup location '/dev/not/there/either/bup_backupdir6.bak' (file already exists?)
+SET @@global.backupdir = 'This_is_really_stupid/not/there/at/all';
+Warnings:
+Warning 1725 The path specified for the system variable backupdir cannot be accessed or is invalid. ref: This_is_really_stupid/not/there/at/all
+Warning 1725 The path specified for the system variable backupdir cannot be accessed or is invalid. ref: This_is_really_stupid/not/there/at/all
+Cleanup
+Reset backupdir
+SET @@global.backupdir = @@global.datadir;
+DROP DATABASE bup_backupdir;
=== added file 'mysql-test/r/backup_concurrent.result'
--- a/mysql-test/r/backup_concurrent.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/backup_concurrent.result 2008-08-08 11:17:37 +0000
@@ -0,0 +1,75 @@
+SET DEBUG_SYNC= 'reset';
+DROP DATABASE IF EXISTS backup_concurrent;
+CREATE DATABASE backup_concurrent;
+USE backup_concurrent;
+Creating Table
+CREATE TABLE t (
+t1 INTEGER NOT NULL,
+t2 CHAR(36),
+PRIMARY KEY (t1)
+);
+---------------------------------------------------
+Testing starting new backup while backup is ongoing
+---------------------------------------------------
+Starting first backup
+SET DEBUG_SYNC= 'after_backup_start_backup SIGNAL running WAIT_FOR backup';
+BACKUP DATABASE backup_concurrent TO 'backup1';
+Waiting for first backup to get going
+SET DEBUG_SYNC= 'now WAIT_FOR running';
+Starting second backup in another connection.
+(Should fail because another backup is running.)
+BACKUP DATABASE backup_concurrent TO 'backup2';
+ERROR HY000: Can't execute this command because another BACKUP/RESTORE operation is in progress
+Insert Data
+INSERT INTO t VALUES (1, 'test');
+Wait for first backup to complete
+SET DEBUG_SYNC= 'now SIGNAL backup';
+backup_id
+#
+---------------------------------------------------
+Testing starting restore while backup is ongoing
+---------------------------------------------------
+Starting backup
+SET DEBUG_SYNC= 'after_backup_start_backup SIGNAL running WAIT_FOR backup';
+BACKUP DATABASE backup_concurrent TO 'backup3';
+Waiting for backup to get going
+SET DEBUG_SYNC= 'now WAIT_FOR running';
+Starting restore in another connection.
+(Should fail because another backup is running.)
+RESTORE FROM 'backup1';
+ERROR HY000: Can't execute this command because another BACKUP/RESTORE operation is in progress
+Insert Data
+INSERT INTO t VALUES (2, 'test');
+Wait for backup to complete
+SET DEBUG_SYNC= 'now SIGNAL backup';
+backup_id
+#
+---------------------------------------------------
+Testing starting backup/restore restore is ongoing
+---------------------------------------------------
+Starting restore
+SET DEBUG_SYNC= 'after_backup_start_restore SIGNAL running WAIT_FOR restore';
+RESTORE FROM 'backup1';
+Waiting for restore to get going
+SET DEBUG_SYNC= 'now WAIT_FOR running';
+Starting backup in another connection.
+(Should fail because restore is running.)
+BACKUP DATABASE backup_concurrent TO 'backup4';
+ERROR HY000: Can't execute this command because another BACKUP/RESTORE operation is in progress
+Insert Data
+INSERT INTO t VALUES (3, 'test');
+Starting a new restore in another connection.
+(Should fail because another restore is running.)
+RESTORE FROM 'backup3';
+ERROR HY000: Can't execute this command because another BACKUP/RESTORE operation is in progress
+Insert Data
+INSERT INTO t VALUES (4, 'test');
+Wait for backup to complete
+SET DEBUG_SYNC= 'now SIGNAL restore';
+backup_id
+#
+
+Test completed. Cleaning up.
+
+DROP DATABASE backup_concurrent;
+SET DEBUG_SYNC= 'reset';
=== modified file 'mysql-test/r/backup_progress.result'
--- a/mysql-test/r/backup_progress.result 2008-07-09 18:37:42 +0000
+++ b/mysql-test/r/backup_progress.result 2008-08-08 17:21:31 +0000
@@ -1,3 +1,33 @@
+
+Checking character set for backup tables
+
+SELECT column_name, character_set_name
+FROM information_schema.columns
+WHERE table_name LIKE 'online_backup'
+AND character_set_name LIKE 'utf8'
+ORDER BY column_name;
+column_name character_set_name
+backup_file utf8
+backup_state utf8
+binlog_file utf8
+command utf8
+drivers utf8
+host_or_server_name utf8
+operation utf8
+username utf8
+user_comment utf8
+
+SELECT column_name, character_set_name
+FROM information_schema.columns
+WHERE table_name LIKE 'online_backup_progress'
+AND character_set_name LIKE 'utf8'
+ORDER BY column_name;
+column_name character_set_name
+notes utf8
+object utf8
+
+Now starting real tests
+
SET DEBUG_SYNC= 'reset';
DROP DATABASE IF EXISTS backup_progress;
DROP TABLE IF EXISTS backup_progress.t1_res;
@@ -78,7 +108,7 @@ start_time #
stop_time #
host_or_server_name localhost
username root
-backup_file backup_progress_orig.bak
+backup_file #
user_comment
command BACKUP DATABASE backup_progress to 'backup_progress_orig.bak'
drivers MyISAM, Default, Snapshot
@@ -135,7 +165,7 @@ start_time #
stop_time #
host_or_server_name localhost
username root
-backup_file backup_progress_orig.bak
+backup_file #
user_comment
command RESTORE FROM 'backup_progress_orig.bak'
drivers MyISAM, Default, Snapshot
=== removed file 'mysql-test/r/backup_view_on_view.result'
--- a/mysql-test/r/backup_view_on_view.result 2008-06-25 13:39:04 +0000
+++ b/mysql-test/r/backup_view_on_view.result 1970-01-01 00:00:00 +0000
@@ -1,38 +0,0 @@
-SET GLOBAL debug="d,backup:d,backup_data";
-DROP DATABASE IF EXISTS db1;
-CREATE DATABASE db1;
-CREATE TABLE db1.t1(a int) ENGINE=INNODB;
-CREATE VIEW db1.v1 AS SELECT * FROM db1.t1;
-CREATE VIEW db1.v2 AS SELECT * FROM db1.v1;
-INSERT INTO db1.t1 VALUES (1),(2),(3),(5),(7),(11);
-BACKUP DATABASE db1 TO 'test.bak';
-backup_id
-#
-RESTORE FROM 'test.bak';
-backup_id
-#
-SELECT * FROM db1.v2;
-a
-1
-2
-3
-5
-7
-11
-SELECT * FROM db1.v1;
-a
-1
-2
-3
-5
-7
-11
-SELECT * FROM db1.t1;
-a
-1
-2
-3
-5
-7
-11
-DROP DATABASE db1;
=== modified file 'mysql-test/r/backup_views.result'
--- a/mysql-test/r/backup_views.result 2008-06-12 09:55:35 +0000
+++ b/mysql-test/r/backup_views.result 2008-08-11 10:41:41 +0000
@@ -6,11 +6,16 @@ DROP DATABASE IF EXISTS bup_db2;
CREATE DATABASE bup_db1;
USE bup_db1;
Creating Table t1
-CREATE TABLE t1(id int not null primary key, name char(10),city varchar(10));
+CREATE TABLE bup_db1.t1(
+id INT NOT NULL PRIMARY KEY,
+name CHAR(10),
+city VARCHAR(10)
+)ENGINE=INNODB;
loading data
-INSERT INTO t1 VALUES
-(1,'aa1','RR1'),(2,'aa2','RR2'),(3,'aa3','RR3'),(4,'aa4','RR4'),(5,'aa5','RR5'),(6,'aa6','RR6'),(7,'aa7','RR7'),(8,'aa8','RR8');
-SELECT * FROM t1;
+INSERT INTO bup_db1.t1 VALUES
+(1,'aa1','RR1'),(2,'aa2','RR2'),(3,'aa3','RR3'),(4,'aa4','RR4'),
+(5,'aa5','RR5'),(6,'aa6','RR6'),(7,'aa7','RR7'),(8,'aa8','RR8');
+SELECT * FROM bup_db1.t1 ORDER BY id;
id name city
1 aa1 RR1
2 aa2 RR2
@@ -21,66 +26,85 @@ id name city
7 aa7 RR7
8 aa8 RR8
Creating Table t3
-CREATE TABLE t3(ccode int, District char(20) not null primary key, scode int, foreign key (scode) references t1(id));
+CREATE TABLE bup_db1.t3(
+ccode INT,
+District CHAR(20) NOT NULL PRIMARY KEY,
+scode INT,
+FOREIGN KEY (scode) REFERENCES bup_db1.t1(id)
+)ENGINE=INNODB;
Loading Data
INSERT INTO t3 VALUES
-(234, 'zuloa',1),(321,'yyy',2),(765,'iug',3),(124,'LKJ',4),(235,'uth',6);
-SELECT * FROM t3;
+(234, 'zuloa',1),(321,'yyy',2),(765,'iug',3),
+(124,'LKJ',4),(235,'uth',6);
+SELECT * FROM bup_db1.t3 ORDER BY scode;
ccode District scode
234 zuloa 1
321 yyy 2
765 iug 3
124 LKJ 4
235 uth 6
+*****Create view from the table bup_db1.t1*******
+CREATE VIEW bup_db1.v1 AS SELECT * FROM bup_db1.t1;
+***Create views from 2 tables(t1 and t3) within same DB bup_db1****
+CREATE VIEW bup_db1.vcomb AS
+SELECT name, city, ccode FROM bup_db1.t1, bup_db1.t3 WHERE id=scode;
+CREATE DATABASE bup_db2;
+CREATE TABLE bup_db2.t2(
+idno INT,
+age INT PRIMARY KEY,
+education CHAR(20) ,
+FOREIGN KEY (idno) REFERENCES bup_db1.t1(id)
+)ENGINE=INNODB;
+INSERT INTO bup_db2.t2 VALUES
+(1,23,'BS'),(2,24,'BE'),(3,19,'School'),(4,28,'MS'),
+(5,43,'PHD'),(6,30,'Doctor'),(7,31,'Lawyer'),(8,27,'Undergrad');
+SELECT * FROM bup_db2.t2 ORDER BY age;
+idno age education
+3 19 School
+1 23 BS
+2 24 BE
+8 27 Undergrad
+4 28 MS
+6 30 Doctor
+7 31 Lawyer
+5 43 PHD
+****Create view in bup_db2****
+CREATE VIEW bup_db2.v2 AS SELECT age, education FROM bup_db2.t2;
+******Create views from combination of 2 databases*******
+CREATE VIEW bup_db2.v3 AS SELECT name, age, education
+FROM bup_db1.t1 , bup_db2.t2 WHERE id=idno;
+*********Create view from another view in bup_db2***********.
+CREATE VIEW bup_db2.vv (N, A, E) AS SELECT * FROM bup_db2.v3;
+*****Create view from other Database********
+CREATE VIEW bup_db2.v4 AS SELECT * FROM bup_db1.t3;
+Rename the view name
+RENAME TABLE bup_db2.v4 to bup_db2.student_details;
+*******Create view from database bup_db2**********
+CREATE VIEW bup_db1.v5 AS SELECT * FROM bup_db2.t2;
Creating Table t5
-CREATE TABLE t5(Gender char(5), cand_age int,foreign key(cand_age) references
-bup_db2.t2(age));
+CREATE TABLE bup_db1.t5(
+Gender CHAR(5),
+cand_age INT,
+FOREIGN KEY(cand_age) REFERENCES bup_db2.t2(age)
+)ENGINE=INNODB;
Loading data into table t5
-INSERT INTO t5 VALUES
-('F',23),('F',24),('M',19),('F',28),('M',43),('F',30),('M',31),('M',27);
-SELECT * FROM t5;
+INSERT INTO bup_db1.t5 VALUES
+('F',23),('F',24),('M',19),('F',28),
+('M',43),('F',30),('M',31),('M',27);
+SELECT * FROM bup_db1.t5 ORDER BY Gender;
Gender cand_age
F 23
F 24
-M 19
F 28
-M 43
F 30
+M 19
+M 43
M 31
M 27
-*****Create views from the table t1 of bup_db1*******
-CREATE VIEW v1 AS SELECT * FROM t1;
-*****Creating views from 2 tables(t1 and t3) within same database******
-CREATE VIEW vcomb AS SELECT name, city, ccode FROM t1, t3 WHERE id=scode;
-CREATE DATABASE bup_db2;
-USE bup_db2;
-CREATE TABLE t2(idno int, age int primary key, education char(20) ,foreign key (idno) references bup_db1.t1(id));
-INSERT INTO t2 VALUES(1,23,'BS'),(2,24,'BE'),(3,19,'school'),(4,28,'MS'),(5,43,'PHD'),(6,30,'Doctor'),(7,31,'Lawyer'),(8,27,'undergrad');
-SELECT * FROM t2;
-idno age education
-1 23 BS
-2 24 BE
-3 19 school
-4 28 MS
-5 43 PHD
-6 30 Doctor
-7 31 Lawyer
-8 27 undergrad
-****Creating View****
-CREATE VIEW v2 AS SELECT age, education FROM t2;
-******Creating Views from combination of 2 databases*******
-CREATE VIEW v3 AS SELECT name, age, education FROM bup_db1.t1 , bup_db2.t2 WHERE id=idno;
-*********Creating View from another view ***********.
-*****Creating View from other Database********
-CREATE VIEW v4 AS SELECT * FROM bup_db1.t3;
-Rename the view name
-RENAME TABLE v4 to student_details;
-USE bup_db1;
-*******Creating View from database bup_db2**********
-CREATE VIEW v5 AS SELECT * FROM bup_db2.t2;
-******Creating View v6********
-USE bup_db1;
-SELECT * FROM t1;
+******Create view v6********
+CREATE VIEW bup_db1.v6 AS SELECT education,gender
+FROM bup_db2.v2, bup_db1.t5 WHERE cand_age=age;
+SELECT * FROM bup_db1.t1 ORDER BY id;
id name city
1 aa1 RR1
2 aa2 RR2
@@ -90,24 +114,24 @@ id name city
6 aa6 RR6
7 aa7 RR7
8 aa8 RR8
-SELECT * FROM t3;
+SELECT * FROM bup_db1.t3 ORDER BY scode;
ccode District scode
234 zuloa 1
321 yyy 2
765 iug 3
124 LKJ 4
235 uth 6
-SELECT * FROM t5;
+SELECT * FROM bup_db1.t5 ORDER BY Gender;
Gender cand_age
F 23
F 24
-M 19
F 28
-M 43
F 30
+M 19
+M 43
M 31
M 27
-SELECT * FROM v1;
+SELECT * FROM bup_db1.v1;
id name city
1 aa1 RR1
2 aa2 RR2
@@ -117,62 +141,81 @@ id name city
6 aa6 RR6
7 aa7 RR7
8 aa8 RR8
-SELECT * FROM vcomb;
+SELECT * FROM bup_db1.vcomb ORDER BY name;
name city ccode
aa1 RR1 234
aa2 RR2 321
aa3 RR3 765
aa4 RR4 124
aa6 RR6 235
-SELECT * FROM v5;
+SELECT * FROM bup_db1.v5 ORDER BY age;
idno age education
+3 19 School
1 23 BS
2 24 BE
-3 19 school
+8 27 Undergrad
4 28 MS
-5 43 PHD
6 30 Doctor
7 31 Lawyer
-8 27 undergrad
+5 43 PHD
+SELECT * FROM bup_db1.v6 ORDER BY education, gender;
+education gender
+BE F
+BS F
+Doctor F
+Lawyer M
+MS F
+PHD M
+School M
+Undergrad M
excercise objects of bup_db2
-USE bup_db2;
-SELECT * FROM t2;
+SELECT * FROM bup_db2.t2 ORDER BY age;
idno age education
+3 19 School
1 23 BS
2 24 BE
-3 19 school
+8 27 Undergrad
4 28 MS
-5 43 PHD
6 30 Doctor
7 31 Lawyer
-8 27 undergrad
-SELECT * FROM v2;
+5 43 PHD
+SELECT * FROM bup_db2.v2 ORDER BY age;
age education
+19 School
23 BS
24 BE
-19 school
+27 Undergrad
28 MS
-43 PHD
30 Doctor
31 Lawyer
-27 undergrad
-SELECT * FROM v3;
+43 PHD
+SELECT * FROM bup_db2.v3 ORDER BY age;
name age education
+aa3 19 School
aa1 23 BS
aa2 24 BE
-aa3 19 school
+aa8 27 Undergrad
+aa4 28 MS
+aa6 30 Doctor
+aa7 31 Lawyer
+aa5 43 PHD
+SELECT * FROM bup_db2.vv;
+N A E
+aa1 23 BS
+aa2 24 BE
+aa3 19 School
aa4 28 MS
aa5 43 PHD
aa6 30 Doctor
aa7 31 Lawyer
-aa8 27 undergrad
-SELECT * FROM student_details;
+aa8 27 Undergrad
+SELECT * FROM bup_db2.student_details;
ccode District scode
-234 zuloa 1
-321 yyy 2
765 iug 3
124 LKJ 4
235 uth 6
+321 yyy 2
+234 zuloa 1
showing objects and create statements.
SHOW FULL TABLES FROM bup_db1;;
Tables_in_bup_db1 t1
@@ -185,6 +228,8 @@ Tables_in_bup_db1 v1
Table_type VIEW
Tables_in_bup_db1 v5
Table_type VIEW
+Tables_in_bup_db1 v6
+Table_type VIEW
Tables_in_bup_db1 vcomb
Table_type VIEW
SHOW FULL TABLES FROM bup_db2;;
@@ -196,14 +241,16 @@ Tables_in_bup_db2 v2
Table_type VIEW
Tables_in_bup_db2 v3
Table_type VIEW
+Tables_in_bup_db2 vv
+Table_type VIEW
SHOW CREATE VIEW bup_db1.v1;;
View v1
-Create View CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `bup_db1`.`v1` AS select `bup_db1`.`t1`.`id` AS `id`,`bup_db1`.`t1`.`name` AS `name`,`bup_db1`.`t1`.`city` AS `city` from `bup_db1`.`t1`
+Create View CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`id` AS `id`,`t1`.`name` AS `name`,`t1`.`city` AS `city` from `t1`
character_set_client latin1
collation_connection latin1_swedish_ci
SHOW CREATE VIEW bup_db1.vcomb;;
View vcomb
-Create View CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `bup_db1`.`vcomb` AS select `bup_db1`.`t1`.`name` AS `name`,`bup_db1`.`t1`.`city` AS `city`,`bup_db1`.`t3`.`ccode` AS `ccode` from (`bup_db1`.`t1` join `bup_db1`.`t3`) where (`bup_db1`.`t1`.`id` = `bup_db1`.`t3`.`scode`)
+Create View CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vcomb` AS select `t1`.`name` AS `name`,`t1`.`city` AS `city`,`t3`.`ccode` AS `ccode` from (`t1` join `t3`) where (`t1`.`id` = `t3`.`scode`)
character_set_client latin1
collation_connection latin1_swedish_ci
SHOW CREATE VIEW bup_db2.v3;;
@@ -211,7 +258,7 @@ View v3
Create View CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `bup_db2`.`v3` AS select `bup_db1`.`t1`.`name` AS `name`,`bup_db2`.`t2`.`age` AS `age`,`bup_db2`.`t2`.`education` AS `education` from (`bup_db1`.`t1` join `bup_db2`.`t2`) where (`bup_db1`.`t1`.`id` = `bup_db2`.`t2`.`idno`)
character_set_client latin1
collation_connection latin1_swedish_ci
-backup data
+backup database
BACKUP DATABASE bup_db1, bup_db2 TO 'bup_objectview.bak';
backup_id
#
@@ -222,8 +269,19 @@ BACKUP DATABASE bup_db2 TO 'bup_objectvi
backup_id
#
dropping database.
+DROP TABLE bup_db1.t3;
+DROP TABLE bup_db1.t5;
+DROP TABLE bup_db2.t2;
DROP DATABASE bup_db1;
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
+DROP DATABASE bup_db1;
+RESTORE FROM 'bup_objectview2.bak';
+ERROR 42S02: Table 'bup_db1.t3' doesn't exist
+DROP DATABASE bup_db2;
RESTORE FROM 'bup_objectview.bak';
backup_id
#
@@ -242,6 +300,8 @@ Tables_in_bup_db1 v1
Table_type VIEW
Tables_in_bup_db1 v5
Table_type VIEW
+Tables_in_bup_db1 v6
+Table_type VIEW
Tables_in_bup_db1 vcomb
Table_type VIEW
SHOW FULL TABLES FROM bup_db2;;
@@ -253,6 +313,8 @@ Tables_in_bup_db2 v2
Table_type VIEW
Tables_in_bup_db2 v3
Table_type VIEW
+Tables_in_bup_db2 vv
+Table_type VIEW
SHOW CREATE VIEW bup_db1.v1;;
View v1
Create View CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `bup_db1`.`v1` AS select `bup_db1`.`t1`.`id` AS `id`,`bup_db1`.`t1`.`name` AS `name`,`bup_db1`.`t1`.`city` AS `city` from `bup_db1`.`t1`
@@ -269,8 +331,7 @@ Create View CREATE ALGORITHM=UNDEFINED D
character_set_client latin1
collation_connection latin1_swedish_ci
****check for view contents after Restore*****
-USE bup_db1;
-SELECT * FROM t1;
+SELECT * FROM bup_db1.t1 ORDER BY id;
id name city
1 aa1 RR1
2 aa2 RR2
@@ -280,24 +341,24 @@ id name city
6 aa6 RR6
7 aa7 RR7
8 aa8 RR8
-SELECT * FROM t3;
+SELECT * FROM bup_db1.t3 ORDER BY scode;
ccode District scode
234 zuloa 1
321 yyy 2
765 iug 3
124 LKJ 4
235 uth 6
-SELECT * FROM t5;
+SELECT * FROM bup_db1.t5 ORDER BY Gender;
Gender cand_age
F 23
F 24
-M 19
F 28
-M 43
F 30
+M 19
+M 43
M 31
M 27
-SELECT * FROM v1;
+SELECT * FROM bup_db1.v1;
id name city
1 aa1 RR1
2 aa2 RR2
@@ -307,79 +368,88 @@ id name city
6 aa6 RR6
7 aa7 RR7
8 aa8 RR8
-SELECT * FROM vcomb;
+SELECT * FROM bup_db1.vcomb ORDER BY name;
name city ccode
aa1 RR1 234
aa2 RR2 321
aa3 RR3 765
aa4 RR4 124
aa6 RR6 235
-SELECT * FROM v5;
+SELECT * FROM bup_db1.v5 ORDER BY age;
idno age education
+3 19 School
1 23 BS
2 24 BE
-3 19 school
+8 27 Undergrad
4 28 MS
-5 43 PHD
6 30 Doctor
7 31 Lawyer
-8 27 undergrad
+5 43 PHD
+SELECT * FROM bup_db1.v6 ORDER BY education, gender;
+education gender
+BE F
+BS F
+Doctor F
+Lawyer M
+MS F
+PHD M
+School M
+Undergrad M
excercise objects of bup_db2
-use bup_db2;
-SELECT * FROM t2;
+SELECT * FROM bup_db2.t2 ORDER BY age;
idno age education
+3 19 School
1 23 BS
2 24 BE
-3 19 school
+8 27 Undergrad
4 28 MS
-5 43 PHD
6 30 Doctor
7 31 Lawyer
-8 27 undergrad
-SELECT * FROM v2;
+5 43 PHD
+SELECT * FROM bup_db2.v2 ORDER BY age;
age education
+19 School
23 BS
24 BE
-19 school
+27 Undergrad
28 MS
-43 PHD
30 Doctor
31 Lawyer
-27 undergrad
-SELECT * FROM v3;
+43 PHD
+SELECT * FROM bup_db2.v3 ORDER BY age;
name age education
+aa3 19 School
+aa1 23 BS
+aa2 24 BE
+aa8 27 Undergrad
+aa4 28 MS
+aa6 30 Doctor
+aa7 31 Lawyer
+aa5 43 PHD
+SELECT * FROM bup_db2.vv;
+N A E
aa1 23 BS
aa2 24 BE
-aa3 19 school
+aa3 19 School
aa4 28 MS
aa5 43 PHD
aa6 30 Doctor
aa7 31 Lawyer
-aa8 27 undergrad
-SELECT * FROM student_details;
+aa8 27 Undergrad
+SELECT * FROM bup_db2.student_details;
ccode District scode
-234 zuloa 1
-321 yyy 2
765 iug 3
124 LKJ 4
235 uth 6
-DROP DATABASE bup_db1;
-DROP DATABASE bup_db2;
-Restoring Database
-RESTORE FROM 'bup_objectview.bak';
-backup_id
-#
-USE bup_db1;
-ALTER TABLE t1 CHANGE id id tinyint not null;
-SHOW CREATE TABLE t1;;
-Table t1
-Create Table CREATE TABLE `t1` (
- `id` tinyint(4) NOT NULL,
- `name` char(10) DEFAULT NULL,
- `city` varchar(10) DEFAULT NULL,
- PRIMARY KEY (`id`)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-SELECT * FROM t1;
+321 yyy 2
+234 zuloa 1
+ALTER TABLE bup_db1.t1 CHANGE name name VARCHAR(10);
+DESCRIBE bup_db1.t1;
+Field Type Null Key Default Extra
+id int(11) NO PRI NULL
+name varchar(10) YES NULL
+city varchar(10) YES NULL
+SELECT * FROM bup_db1.t1 ORDER BY id;
id name city
1 aa1 RR1
2 aa2 RR2
@@ -389,17 +459,7 @@ id name city
6 aa6 RR6
7 aa7 RR7
8 aa8 RR8
-DELETE FROM t1 WHERE id=7;
-SELECT * FROM t1;
-id name city
-1 aa1 RR1
-2 aa2 RR2
-3 aa3 RR3
-4 aa4 RR4
-5 aa5 RR5
-6 aa6 RR6
-8 aa8 RR8
-SELECT * FROM v1;
+SELECT * FROM bup_db1.v1;
id name city
1 aa1 RR1
2 aa2 RR2
@@ -407,37 +467,40 @@ id name city
4 aa4 RR4
5 aa5 RR5
6 aa6 RR6
+7 aa7 RR7
8 aa8 RR8
-USE bup_db2;
-SELECT * FROM v3;
+SELECT * FROM bup_db2.v3 ORDER BY age;
name age education
+aa3 19 School
aa1 23 BS
aa2 24 BE
-aa3 19 school
+aa8 27 Undergrad
aa4 28 MS
-aa5 43 PHD
aa6 30 Doctor
-aa8 27 undergrad
+aa7 31 Lawyer
+aa5 43 PHD
BACKUP DATABASE bup_db1, bup_db2 TO 'bup_objectview3.bak';
backup_id
#
+DROP TABLE bup_db1.t3;
+DROP TABLE bup_db1.t5;
+DROP TABLE bup_db2.t2;
DROP DATABASE bup_db1;
DROP DATABASE bup_db2;
RESTORE FROM 'bup_objectview3.bak';
backup_id
#
-USE bup_db2;
-SELECT * FROM v3;
+SELECT * FROM bup_db2.v3 ORDER BY age;
name age education
+aa3 19 School
aa1 23 BS
aa2 24 BE
-aa3 19 school
+aa8 27 Undergrad
aa4 28 MS
-aa5 43 PHD
aa6 30 Doctor
-aa8 27 undergrad
-USE bup_db1;
-SELECT * FROM t1;
+aa7 31 Lawyer
+aa5 43 PHD
+SELECT * FROM bup_db1.t1 ORDER BY id;
id name city
1 aa1 RR1
2 aa2 RR2
@@ -445,9 +508,91 @@ id name city
4 aa4 RR4
5 aa5 RR5
6 aa6 RR6
+7 aa7 RR7
8 aa8 RR8
+*** ENTER Backup of database with missing view dependency
+*** should fail but not crash server
+*** Test for bug#34902 ***
+initializing test
+DROP TABLE bup_db1.t3;
+DROP TABLE bup_db1.t5;
+DROP TABLE bup_db2.t2;
+DROP DATABASE bup_db1;
+DROP DATABASE bup_db2;
+RESTORE FROM 'bup_objectview.bak';
+backup_id
+#
+SELECT * FROM bup_db1.t1;
+id name city
+1 aa1 RR1
+2 aa2 RR2
+3 aa3 RR3
+4 aa4 RR4
+5 aa5 RR5
+6 aa6 RR6
+7 aa7 RR7
+8 aa8 RR8
+SELECT * FROM bup_db1.v1;
+id name city
+1 aa1 RR1
+2 aa2 RR2
+3 aa3 RR3
+4 aa4 RR4
+5 aa5 RR5
+6 aa6 RR6
+7 aa7 RR7
+8 aa8 RR8
+DROP TABLE bup_db1.t3;
+DROP TABLE bup_db1.t5;
+DROP TABLE bup_db2.t2;
+DROP TABLE bup_db1.t1;
+
+Testing backup with missing view dependency in same db
+
+SELECT * FROM bup_db1.v1;
+ERROR HY000: View 'bup_db1.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+BACKUP DATABASE bup_db1 TO 'bup_shouldfail1.bak';
+ERROR HY000: Failed to add view `bup_db1`.`v1` to the catalog
+
+Testing backup with missing view dependency in other db
+
+USE bup_db2;
+SELECT * from bup_db2.v3;
+ERROR HY000: View 'bup_db2.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+BACKUP DATABASE bup_db2 TO 'bup_shouldfail2.bak';
+ERROR HY000: Failed to add view `bup_db2`.`student_details` to the catalog
+
+*** EXIT Backup of database with missing view dependency
+
+
+*** ENTER Backup of database with altered view should report error, not crash server
+Test for bug#34867
+initializing test
+DROP DATABASE bup_db1;
+DROP DATABASE bup_db2;
+RESTORE FROM 'bup_objectview.bak';
+backup_id
+#
+USE bup_db1;
+CREATE VIEW alter1 AS SELECT 5;
+CREATE VIEW alter2 AS SELECT * FROM alter1;
+ALTER VIEW alter1 AS SELECT 6;
+
+Testing view selecting from altered view
+
+SELECT * FROM alter2;
+ERROR HY000: View 'bup_db1.alter2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+BACKUP DATABASE bup_db1 TO 'bup_alterview.bak';
+ERROR HY000: View 'bup_db1.alter2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+
+*** EXIT Backup of database with altered view
+
+
*** DROP bup_db1, bup_db2 DATABASE ****
+DROP TABLE bup_db1.t3;
+DROP TABLE bup_db1.t5;
+DROP TABLE bup_db2.t2;
DROP DATABASE bup_db1;
DROP DATABASE bup_db2;
=== added file 'mysql-test/t/backup_backupdir.test'
--- a/mysql-test/t/backup_backupdir.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/backup_backupdir.test 2008-08-08 17:21:31 +0000
@@ -0,0 +1,109 @@
+#
+# This test is designed to test the new backupdir variable.
+#
+
+--source include/not_embedded.inc
+
+--echo Reset backupdir
+SET @@global.backupdir = @@global.datadir;
+
+--disable_warnings
+DROP DATABASE IF EXISTS bup_backupdir;
+--enable_warnings
+
+--echo Create a database
+CREATE DATABASE bup_backupdir;
+CREATE TABLE bup_backupdir.t1(a INT);
+INSERT INTO bup_backupdir.t1 VALUES (1), (2), (3);
+
+#
+# The following tests the backupdir variable by changing it to
+# redirect the output of the backup command/input of the restore
+# command.
+#
+
+--error 0,1,2
+rmdir $MYSQLTEST_VARDIR/tmp/backup;
+
+--echo Create a directory for backup images
+mkdir $MYSQLTEST_VARDIR/tmp/backup;
+
+--echo Reset backupdir
+SET @@global.backupdir = '../tmp/backup';
+
+--echo Perform backup
+--replace_column 1 #
+BACKUP DATABASE bup_backupdir TO 'bup_backupdir1.bak';
+
+--echo Ensure backup image file went to the correct location
+--echo $MYSQLTEST_DIR/backup/bup_backupdir.bak
+--file_exists $MYSQLTEST_VARDIR/tmp/backup/bup_backupdir1.bak
+
+--echo Perform restore
+--replace_column 1 #
+RESTORE FROM 'bup_backupdir1.bak';
+
+--echo Now do the backup and restore by specifying a path.
+
+--echo Perform backup
+--replace_column 1 #
+BACKUP DATABASE bup_backupdir TO '../bup_backupdir2.bak';
+
+--echo Ensure backup image file went to the correct location
+--file_exists $MYSQLTEST_VARDIR/tmp/bup_backupdir2.bak
+
+--echo Perform restore
+--replace_column 1 #
+RESTORE FROM '../bup_backupdir2.bak';
+
+--echo Perform backup
+--replace_column 1 #
+BACKUP DATABASE bup_backupdir TO '../../bup_backupdir3.bak';
+
+--echo Ensure backup image file went to the correct location
+--file_exists $MYSQLTEST_VARDIR/bup_backupdir3.bak
+
+--echo Reset backupdir with ending /
+SET @@global.backupdir = '../tmp/backup/';
+
+--echo Perform backup
+--replace_column 1 #
+BACKUP DATABASE bup_backupdir TO '../../bup_backupdir4.bak';
+
+--echo Ensure backup image file went to the correct location
+--file_exists $MYSQLTEST_VARDIR/bup_backupdir4.bak
+
+--echo Try a backup to an invalid relative path.
+--error ER_BACKUP_WRITE_LOC
+BACKUP DATABASE bup_backupdir TO '../../../../../../../../../../../../../../../../../../bup_backupdir5.bak';
+
+--echo Try a backup to an invalid hard path.
+--error ER_BACKUP_WRITE_LOC
+BACKUP DATABASE bup_backupdir TO '/dev/not/there/either/bup_backupdir6.bak';
+
+#
+# Attempt to set the backupdir to something invalid.
+#
+SET @@global.backupdir = 'This_is_really_stupid/not/there/at/all';
+
+--echo Cleanup
+
+--echo Reset backupdir
+SET @@global.backupdir = @@global.datadir;
+
+DROP DATABASE bup_backupdir;
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/tmp/bup_backupdir1.bak
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/tmp/backup/bup_backupdir2.bak
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_backupdir3.bak
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_backupdir4.bak
+
+--error 0,1
+rmdir $MYSQLTEST_VARDIR/tmp/backup;
=== added file 'mysql-test/t/backup_concurrent.test'
--- a/mysql-test/t/backup_concurrent.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/backup_concurrent.test 2008-08-08 11:17:37 +0000
@@ -0,0 +1,121 @@
+###########################################################################
+# Author: Oystein Grovlen
+# Date: 2008-07-31
+# Purpose: To test starting backups/retore in parallel
+###############################################################################
+--source include/not_embedded.inc
+--source include/have_debug_sync.inc
+
+#Create Database and object view for this test.
+
+--disable_warnings
+SET DEBUG_SYNC= 'reset';
+DROP DATABASE IF EXISTS backup_concurrent;
+--enable_warnings
+
+CREATE DATABASE backup_concurrent;
+USE backup_concurrent;
+
+#Create table
+
+--echo Creating Table
+CREATE TABLE t (
+t1 INTEGER NOT NULL,
+t2 CHAR(36),
+PRIMARY KEY (t1)
+);
+
+--echo ---------------------------------------------------
+--echo Testing starting new backup while backup is ongoing
+--echo ---------------------------------------------------
+--echo Starting first backup
+connect (backup,localhost,root,,);
+SET DEBUG_SYNC= 'after_backup_start_backup SIGNAL running WAIT_FOR backup';
+send BACKUP DATABASE backup_concurrent TO 'backup1';
+
+connection default;
+--echo Waiting for first backup to get going
+SET DEBUG_SYNC= 'now WAIT_FOR running';
+--echo Starting second backup in another connection.
+--echo (Should fail because another backup is running.)
+--error ER_BACKUP_RUNNING
+BACKUP DATABASE backup_concurrent TO 'backup2';
+
+--echo Insert Data
+INSERT INTO t VALUES (1, 'test');
+
+--echo Wait for first backup to complete
+SET DEBUG_SYNC= 'now SIGNAL backup';
+connection backup;
+replace_column 1 #;
+reap;
+
+--echo ---------------------------------------------------
+--echo Testing starting restore while backup is ongoing
+--echo ---------------------------------------------------
+--echo Starting backup
+SET DEBUG_SYNC= 'after_backup_start_backup SIGNAL running WAIT_FOR backup';
+send BACKUP DATABASE backup_concurrent TO 'backup3';
+
+connection default;
+--echo Waiting for backup to get going
+SET DEBUG_SYNC= 'now WAIT_FOR running';
+--echo Starting restore in another connection.
+--echo (Should fail because another backup is running.)
+--error ER_BACKUP_RUNNING
+RESTORE FROM 'backup1';
+
+--echo Insert Data
+INSERT INTO t VALUES (2, 'test');
+
+--echo Wait for backup to complete
+SET DEBUG_SYNC= 'now SIGNAL backup';
+connection backup;
+replace_column 1 #;
+reap;
+
+--echo ---------------------------------------------------
+--echo Testing starting backup/restore restore is ongoing
+--echo ---------------------------------------------------
+--echo Starting restore
+SET DEBUG_SYNC= 'after_backup_start_restore SIGNAL running WAIT_FOR restore';
+send RESTORE FROM 'backup1';
+
+connection default;
+--echo Waiting for restore to get going
+SET DEBUG_SYNC= 'now WAIT_FOR running';
+
+--echo Starting backup in another connection.
+--echo (Should fail because restore is running.)
+--error ER_BACKUP_RUNNING
+BACKUP DATABASE backup_concurrent TO 'backup4';
+
+--echo Insert Data
+INSERT INTO t VALUES (3, 'test');
+
+--echo Starting a new restore in another connection.
+--echo (Should fail because another restore is running.)
+--error ER_BACKUP_RUNNING
+RESTORE FROM 'backup3';
+
+--echo Insert Data
+INSERT INTO t VALUES (4, 'test');
+
+--echo Wait for backup to complete
+SET DEBUG_SYNC= 'now SIGNAL restore';
+connection backup;
+replace_column 1 #;
+reap;
+
+
+# Test cleanup section
+
+--echo
+--echo Test completed. Cleaning up.
+--echo
+
+DROP DATABASE backup_concurrent;
+SET DEBUG_SYNC= 'reset';
+--remove_file $MYSQLTEST_VARDIR/master-data/backup1
+--remove_file $MYSQLTEST_VARDIR/master-data/backup3
+
=== modified file 'mysql-test/t/backup_progress.test'
--- a/mysql-test/t/backup_progress.test 2008-06-25 13:39:04 +0000
+++ b/mysql-test/t/backup_progress.test 2008-08-08 17:21:31 +0000
@@ -8,6 +8,30 @@
--source include/have_innodb.inc
--source include/not_embedded.inc
+# bug#33836 backup tables should have charset utf8
+
+--echo
+--echo Checking character set for backup tables
+--echo
+
+SELECT column_name, character_set_name
+FROM information_schema.columns
+WHERE table_name LIKE 'online_backup'
+ AND character_set_name LIKE 'utf8'
+ORDER BY column_name;
+
+--echo
+
+SELECT column_name, character_set_name
+FROM information_schema.columns
+WHERE table_name LIKE 'online_backup_progress'
+ AND character_set_name LIKE 'utf8'
+ORDER BY column_name;
+
+--echo
+--echo Now starting real tests
+--echo
+
#
# Preparative cleanup.
#
@@ -107,7 +131,7 @@ connection con2;
reap;
#Show results
---replace_column 1 # 2 # 3 # 4 # 10 # 11 # 12 #
+--replace_column 1 # 2 # 3 # 4 # 10 # 11 # 12 # 15 #
--query_vertical SELECT ob.* FROM mysql.online_backup AS ob JOIN backup_progress.t1_res AS t1 ON ob.backup_id = t1.id;
--replace_column 1 # 3 # 4 #
SELECT obp.* FROM mysql.online_backup_progress AS obp JOIN backup_progress.t1_res AS t1 ON obp.backup_id = t1.id;
@@ -156,7 +180,7 @@ reap;
DELETE FROM backup_progress.t1_res;
SELECT MAX(backup_id) INTO @bup_id FROM mysql.online_backup WHERE command LIKE "RESTORE FROM%";
INSERT INTO backup_progress.t1_res (id) VALUES (@bup_id);
---replace_column 1 # 2 # 3 # 4 # 10 # 11 # 12 #
+--replace_column 1 # 2 # 3 # 4 # 10 # 11 # 12 # 15 #
--query_vertical SELECT ob.* FROM mysql.online_backup AS ob JOIN backup_progress.t1_res AS t1 ON ob.backup_id = t1.id;
--replace_column 1 # 3 # 4 #
SELECT obp.* FROM mysql.online_backup_progress AS obp JOIN backup_progress.t1_res AS t1 ON obp.backup_id = t1.id;
=== removed file 'mysql-test/t/backup_view_on_view.test'
--- a/mysql-test/t/backup_view_on_view.test 2008-06-25 13:39:04 +0000
+++ b/mysql-test/t/backup_view_on_view.test 1970-01-01 00:00:00 +0000
@@ -1,32 +0,0 @@
-# Test case for bug#34758
-
---source include/not_embedded.inc
---source include/have_debug.inc
---source include/have_innodb.inc
-
-# Setup the server to use the backup breakpoints
-SET GLOBAL debug="d,backup:d,backup_data";
-
---disable_warnings
-DROP DATABASE IF EXISTS db1;
---enable_warnings
-
-CREATE DATABASE db1;
-
-CREATE TABLE db1.t1(a int) ENGINE=INNODB;
-CREATE VIEW db1.v1 AS SELECT * FROM db1.t1;
-CREATE VIEW db1.v2 AS SELECT * FROM db1.v1;
-
-INSERT INTO db1.t1 VALUES (1),(2),(3),(5),(7),(11);
-
-replace_column 1 #;
-BACKUP DATABASE db1 TO 'test.bak';
-replace_column 1 #;
-RESTORE FROM 'test.bak';
-
-SELECT * FROM db1.v2;
-SELECT * FROM db1.v1;
-SELECT * FROM db1.t1;
-
-DROP DATABASE db1;
-
=== modified file 'mysql-test/t/backup_views.test'
--- a/mysql-test/t/backup_views.test 2008-06-12 09:55:35 +0000
+++ b/mysql-test/t/backup_views.test 2008-08-11 10:41:41 +0000
@@ -25,140 +25,148 @@ connect (breakpoints,localhost,root,,);
DROP DATABASE IF EXISTS bup_db1;
DROP DATABASE IF EXISTS bup_db2;
-
-#We are creating 2 databases bup_db1 and bup_db2 to accomplish wide testing of views in order to check their consistency # after BACKUP AND RESTORE.
+#
+# We are creating 2 databases bup_db1 and bup_db2 to accomplish wide testing
+# of views in order to check their consistency after BACKUP AND RESTORE.
# In bup_db1 DATABASE consists of tables :t1 t3 t5
-# and views v1(based on t1 alone), vcomb(based on t1 and t3), v5( based on bup_db2.t2), v6(based on bup_db2.v2,bup_db1.t5)
+# and views v1(based on t1 alone), vcomb(based on t1 and t3),
+# v5( based on bup_db2.t2), v6(based on bup_db2.v2,bup_db1.t5)
#
# In bup_db2,it consists table t2
-# views v2(based on t2), v3( based on combination of bup_db1 and bup_db2),v4( based on bup_db1.t3), vv( based on v3)
+# views v2(based on t2), v3( based on combination of bup_db1 and bup_db2),
+# v4( based on bup_db1.t3), vv( based on v3)
#
--enable_warnings
-
CREATE DATABASE bup_db1;
USE bup_db1;
#Create table and load with data.
--echo Creating Table t1
-CREATE TABLE t1(id int not null primary key, name char(10),city varchar(10));
+CREATE TABLE bup_db1.t1(
+id INT NOT NULL PRIMARY KEY,
+name CHAR(10),
+city VARCHAR(10)
+)ENGINE=INNODB;
--echo loading data
-INSERT INTO t1 VALUES
-(1,'aa1','RR1'),(2,'aa2','RR2'),(3,'aa3','RR3'),(4,'aa4','RR4'),(5,'aa5','RR5'),(6,'aa6','RR6'),(7,'aa7','RR7'),(8,'aa8','RR8');
+INSERT INTO bup_db1.t1 VALUES
+(1,'aa1','RR1'),(2,'aa2','RR2'),(3,'aa3','RR3'),(4,'aa4','RR4'),
+(5,'aa5','RR5'),(6,'aa6','RR6'),(7,'aa7','RR7'),(8,'aa8','RR8');
-SELECT * FROM t1;
+SELECT * FROM bup_db1.t1 ORDER BY id;
--echo Creating Table t3
-CREATE TABLE t3(ccode int, District char(20) not null primary key, scode int, foreign key (scode) references t1(id));
+CREATE TABLE bup_db1.t3(
+ccode INT,
+District CHAR(20) NOT NULL PRIMARY KEY,
+scode INT,
+FOREIGN KEY (scode) REFERENCES bup_db1.t1(id)
+)ENGINE=INNODB;
--echo Loading Data
INSERT INTO t3 VALUES
-(234, 'zuloa',1),(321,'yyy',2),(765,'iug',3),(124,'LKJ',4),(235,'uth',6);
-
-SELECT * FROM t3;
-
---echo Creating Table t5
-
-CREATE TABLE t5(Gender char(5), cand_age int,foreign key(cand_age) references
-bup_db2.t2(age));
-
---echo Loading data into table t5
-
-INSERT INTO t5 VALUES
-('F',23),('F',24),('M',19),('F',28),('M',43),('F',30),('M',31),('M',27);
+(234, 'zuloa',1),(321,'yyy',2),(765,'iug',3),
+(124,'LKJ',4),(235,'uth',6);
-SELECT * FROM t5;
+SELECT * FROM bup_db1.t3 ORDER BY scode;
---echo *****Create views from the table t1 of bup_db1*******
+--echo *****Create view from the table bup_db1.t1*******
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE VIEW bup_db1.v1 AS SELECT * FROM bup_db1.t1;
---echo *****Creating views from 2 tables(t1 and t3) within same database******
-
-CREATE VIEW vcomb AS SELECT name, city, ccode FROM t1, t3 WHERE id=scode;
+--echo ***Create views from 2 tables(t1 and t3) within same DB bup_db1****
+CREATE VIEW bup_db1.vcomb AS
+SELECT name, city, ccode FROM bup_db1.t1, bup_db1.t3 WHERE id=scode;
CREATE DATABASE bup_db2;
-USE bup_db2;
-
-CREATE TABLE t2(idno int, age int primary key, education char(20) ,foreign key (idno) references bup_db1.t1(id));
-INSERT INTO t2 VALUES(1,23,'BS'),(2,24,'BE'),(3,19,'school'),(4,28,'MS'),(5,43,'PHD'),(6,30,'Doctor'),(7,31,'Lawyer'),(8,27,'undergrad');
+CREATE TABLE bup_db2.t2(
+idno INT,
+age INT PRIMARY KEY,
+education CHAR(20) ,
+FOREIGN KEY (idno) REFERENCES bup_db1.t1(id)
+)ENGINE=INNODB;
+INSERT INTO bup_db2.t2 VALUES
+(1,23,'BS'),(2,24,'BE'),(3,19,'School'),(4,28,'MS'),
+(5,43,'PHD'),(6,30,'Doctor'),(7,31,'Lawyer'),(8,27,'Undergrad');
-SELECT * FROM t2;
+SELECT * FROM bup_db2.t2 ORDER BY age;
---echo ****Creating View****
+--echo ****Create view in bup_db2****
-CREATE VIEW v2 AS SELECT age, education FROM t2;
+CREATE VIEW bup_db2.v2 AS SELECT age, education FROM bup_db2.t2;
---echo ******Creating Views from combination of 2 databases*******
+--echo ******Create views from combination of 2 databases*******
-CREATE VIEW v3 AS SELECT name, age, education FROM bup_db1.t1 , bup_db2.t2 WHERE id=idno;
+CREATE VIEW bup_db2.v3 AS SELECT name, age, education
+FROM bup_db1.t1 , bup_db2.t2 WHERE id=idno;
---echo *********Creating View from another view ***********.
+--echo *********Create view from another view in bup_db2***********.
-#Bug#35347 Mysql Server crash while doing restore with views for default driver
+# Bug#35347 Mysql Server crash while doing restore with views for default driver
# BUG#34758 Server crashes if database with views backed up using CS driver
-#Creatig view from another view is possible if bug#35347 and bug#34758 is fixed.
+#Creating view from another view is possible if bug#35347 and bug#34758is fixed.
-#CREATE VIEW vv (N, A, E) AS SELECT * FROM v3;
+CREATE VIEW bup_db2.vv (N, A, E) AS SELECT * FROM bup_db2.v3;
---echo *****Creating View from other Database********
+--echo *****Create view from other Database********
-CREATE VIEW v4 AS SELECT * FROM bup_db1.t3;
+CREATE VIEW bup_db2.v4 AS SELECT * FROM bup_db1.t3;
--echo Rename the view name
-RENAME TABLE v4 to student_details;
+RENAME TABLE bup_db2.v4 to bup_db2.student_details;
-USE bup_db1;
+--echo *******Create view from database bup_db2**********
---echo *******Creating View from database bup_db2**********
+CREATE VIEW bup_db1.v5 AS SELECT * FROM bup_db2.t2;
-CREATE VIEW v5 AS SELECT * FROM bup_db2.t2;
+--echo Creating Table t5
---echo ******Creating View v6********
+CREATE TABLE bup_db1.t5(
+Gender CHAR(5),
+cand_age INT,
+FOREIGN KEY(cand_age) REFERENCES bup_db2.t2(age)
+)ENGINE=INNODB;
-#Bug#36213 Restore fails for a database that has views created using another database .
+--echo Loading data into table t5
-#CREATE VIEW v6 AS SELECT education,gender FROM bup_db2.v2, t5 WHERE cand_age=age;
+INSERT INTO bup_db1.t5 VALUES
+('F',23),('F',24),('M',19),('F',28),
+('M',43),('F',30),('M',31),('M',27);
+
+SELECT * FROM bup_db1.t5 ORDER BY Gender;
+
+#Bug#36213 Restore fails for a database that has views created using
+#another database .
+
+--echo ******Create view v6********
+CREATE VIEW bup_db1.v6 AS SELECT education,gender
+FROM bup_db2.v2, bup_db1.t5 WHERE cand_age=age;
#Excercise the objects of bup_db1
-USE bup_db1;
-
-SELECT * FROM t1;
-
-SELECT * FROM t3;
-
-SELECT * FROM t5;
-
-SELECT * FROM v1;
-
-SELECT * FROM vcomb;
-
-SELECT * FROM v5;
-
-#SELECT * FROM v6;
+SELECT * FROM bup_db1.t1 ORDER BY id;
+SELECT * FROM bup_db1.t3 ORDER BY scode;
+SELECT * FROM bup_db1.t5 ORDER BY Gender;
+SELECT * FROM bup_db1.v1;
+SELECT * FROM bup_db1.vcomb ORDER BY name;
+SELECT * FROM bup_db1.v5 ORDER BY age;
+SELECT * FROM bup_db1.v6 ORDER BY education, gender;
--echo excercise objects of bup_db2
-USE bup_db2;
-
-SELECT * FROM t2;
-
-SELECT * FROM v2;
-
-SELECT * FROM v3;
-
-#SELECT * FROM vv;
-
-SELECT * FROM student_details; #view v4 is renamed as student_details
+SELECT * FROM bup_db2.t2 ORDER BY age;
+SELECT * FROM bup_db2.v2 ORDER BY age;
+SELECT * FROM bup_db2.v3 ORDER BY age;
+SELECT * FROM bup_db2.vv;
+SELECT * FROM bup_db2.student_details; #view v4 is renamed as student_details
#Show the data and Create statements
@@ -170,7 +178,8 @@ SELECT * FROM student_details; #view v4
--query_vertical SHOW CREATE VIEW bup_db2.v3;
#Backup and restore data.
---echo backup data
+--echo backup database
+
replace_column 1 #;
BACKUP DATABASE bup_db1, bup_db2 TO 'bup_objectview.bak';
@@ -181,18 +190,34 @@ replace_column 1 #;
BACKUP DATABASE bup_db2 TO 'bup_objectview2.bak';
--echo dropping database.
+DROP TABLE bup_db1.t3;
+DROP TABLE bup_db1.t5;
+DROP TABLE bup_db2.t2;
DROP DATABASE bup_db1;
-
DROP DATABASE bup_db2;
-#RESTORE FROM bup_objectview.bak;
+--echo Restore database.
+
+# Individual databases cannot be restored because of VIEW DEPENDENCY
+# For restoring we need base tables in the database, otherwise the
+# Restore will fail. Once this bug is fixed, we can remove the '#'
+# for the restore below.
-#Individual databases cannot be restored because of VIEW DEPENDENCY
+--echo restore database with view dependency to other, non-existing db
-#--error 1146
-#RESTORE FROM 'bup_objectview1.bak';
-#--error 1146
-#RESTORE FROM 'bup_objectview2.bak';
+--error ER_NO_SUCH_TABLE
+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
+RESTORE FROM 'bup_objectview2.bak';
+
+# An incomplete bup_db2 was created by the failing restore operation.
+# Remove it before reverting to the working backup image
+DROP DATABASE bup_db2;
replace_column 1 #;
RESTORE FROM 'bup_objectview.bak';
@@ -209,77 +234,132 @@ RESTORE FROM 'bup_objectview.bak';
--echo ****check for view contents after Restore*****
#Excercise the objects of bup_db1
-USE bup_db1;
-SELECT * FROM t1;
-SELECT * FROM t3;
+SELECT * FROM bup_db1.t1 ORDER BY id;
+SELECT * FROM bup_db1.t3 ORDER BY scode;
+SELECT * FROM bup_db1.t5 ORDER BY Gender;
+SELECT * FROM bup_db1.v1;
+SELECT * FROM bup_db1.vcomb ORDER BY name;
+SELECT * FROM bup_db1.v5 ORDER BY age;
+SELECT * FROM bup_db1.v6 ORDER BY education, gender;
-SELECT * FROM t5;
+--echo excercise objects of bup_db2
-SELECT * FROM v1;
+SELECT * FROM bup_db2.t2 ORDER BY age;
+SELECT * FROM bup_db2.v2 ORDER BY age;
+SELECT * FROM bup_db2.v3 ORDER BY age;
+SELECT * FROM bup_db2.vv;
+SELECT * FROM bup_db2.student_details;
-SELECT * FROM vcomb;
+#Alter table t1 and take BACKUP to see if view is not affected.
-SELECT * FROM v5;
+ALTER TABLE bup_db1.t1 CHANGE name name VARCHAR(10);
+DESCRIBE bup_db1.t1;
+SELECT * FROM bup_db1.t1 ORDER BY id;
+SELECT * FROM bup_db1.v1;
+SELECT * FROM bup_db2.v3 ORDER BY age;
-#SELECT * FROM v6;
---echo excercise objects of bup_db2
-use bup_db2;
-SELECT * FROM t2;
-
-SELECT * FROM v2;
+replace_column 1 #;
+BACKUP DATABASE bup_db1, bup_db2 TO 'bup_objectview3.bak';
-SELECT * FROM v3;
+DROP TABLE bup_db1.t3;
+DROP TABLE bup_db1.t5;
+DROP TABLE bup_db2.t2;
+DROP DATABASE bup_db1;
+DROP DATABASE bup_db2;
-#SELECT * FROM vv;
+replace_column 1 #;
+RESTORE FROM 'bup_objectview3.bak';
-SELECT * FROM student_details;
+SELECT * FROM bup_db2.v3 ORDER BY age;
+SELECT * FROM bup_db1.t1 ORDER BY id;
+--echo
+--echo *** ENTER Backup of database with missing view dependency
+--echo *** should fail but not crash server
+--echo *** Test for bug#34902 ***
+
+--echo initializing test
+
+# start with the backed up database
+DROP TABLE bup_db1.t3;
+DROP TABLE bup_db1.t5;
+DROP TABLE bup_db2.t2;
DROP DATABASE bup_db1;
DROP DATABASE bup_db2;
---echo Restoring Database
-
replace_column 1 #;
RESTORE FROM 'bup_objectview.bak';
-USE bup_db1;
-
-#Alter table t1 and take BACKUP to see if view is not affected.
-
-ALTER TABLE t1 CHANGE id id tinyint not null;
---query_vertical SHOW CREATE TABLE t1;
+# check that table t1 and v1 are initially correct
+SELECT * FROM bup_db1.t1;
+SELECT * FROM bup_db1.v1;
+
+DROP TABLE bup_db1.t3;
+DROP TABLE bup_db1.t5;
+DROP TABLE bup_db2.t2;
+DROP TABLE bup_db1.t1;
-SELECT * FROM t1;
+--echo
+--echo Testing backup with missing view dependency in same db
+--echo
-DELETE FROM t1 WHERE id=7;
-SELECT * FROM t1;
+# v1 selects from t1, and select now reports error
+--error ER_VIEW_INVALID
+SELECT * FROM bup_db1.v1;
+
+# try to backup - v1 selects from t1 and backup should now fail
+--error ER_BACKUP_CATALOG_ADD_VIEW
+BACKUP DATABASE bup_db1 TO 'bup_shouldfail1.bak';
-SELECT * FROM v1;
+--echo
+--echo Testing backup with missing view dependency in other db
+--echo
USE bup_db2;
-SELECT * FROM v3;
+--error ER_VIEW_INVALID
+SELECT * from bup_db2.v3;
+# try to backup - v3 selects from bup_db1.t1 and backup should now fail
+--error ER_BACKUP_CATALOG_ADD_VIEW
+BACKUP DATABASE bup_db2 TO 'bup_shouldfail2.bak';
-#BUG#35249 Mysql server crash for delete operation followed by backup for Default Drivers.
+--echo
+--echo *** EXIT Backup of database with missing view dependency
+--echo
-#DELETE FROM t2 WHERE age=24;
-#SELECT * FROM t2;
-#SELECT * FROM v3;
+--echo
+--echo *** ENTER Backup of database with altered view should report error, not crash server
+--echo Test for bug#34867
-replace_column 1 #;
-BACKUP DATABASE bup_db1, bup_db2 TO 'bup_objectview3.bak';
+--echo initializing test
+# start with the backed up database
DROP DATABASE bup_db1;
DROP DATABASE bup_db2;
replace_column 1 #;
-RESTORE FROM 'bup_objectview3.bak';
-
-USE bup_db2;
-SELECT * FROM v3;
+RESTORE FROM 'bup_objectview.bak';
USE bup_db1;
-SELECT * FROM t1;
+CREATE VIEW alter1 AS SELECT 5;
+CREATE VIEW alter2 AS SELECT * FROM alter1;
+ALTER VIEW alter1 AS SELECT 6;
+
+--echo
+--echo Testing view selecting from altered view
+--echo
+
+--error ER_VIEW_INVALID
+SELECT * FROM alter2;
+
+#fails
+--error ER_VIEW_INVALID
+BACKUP DATABASE bup_db1 TO 'bup_alterview.bak';
+
+--echo
+--echo *** EXIT Backup of database with altered view
+--echo
+
# Test cleanup section
@@ -287,15 +367,21 @@ SELECT * FROM t1;
--echo *** DROP bup_db1, bup_db2 DATABASE ****
--echo
-DROP DATABASE bup_db1;
+DROP TABLE bup_db1.t3;
+DROP TABLE bup_db1.t5;
+DROP TABLE bup_db2.t2;
+DROP DATABASE bup_db1;
DROP DATABASE bup_db2;
-
--remove_file $MYSQLTEST_VARDIR/master-data/bup_objectview.bak
-
--remove_file $MYSQLTEST_VARDIR/master-data/bup_objectview1.bak
-
--remove_file $MYSQLTEST_VARDIR/master-data/bup_objectview2.bak
--remove_file $MYSQLTEST_VARDIR/master-data/bup_objectview3.bak
-#BUG#35249 Mysql server crash for delete operation followed by backup for Default Drivers.
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_shouldfail1.bak
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_shouldfail2.bak
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_alterview.bak
+
=== modified file 'mysql-test/t/disabled.def'
--- a/mysql-test/t/disabled.def 2008-07-09 07:12:43 +0000
+++ b/mysql-test/t/disabled.def 2008-07-16 08:43:42 +0000
@@ -44,3 +44,4 @@ max_heap_table_size_basic_32 : Bug#36877
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
=== modified file 'scripts/mysql_system_tables.sql'
--- a/scripts/mysql_system_tables.sql 2008-07-09 18:37:42 +0000
+++ b/scripts/mysql_system_tables.sql 2008-08-08 12:59:55 +0000
@@ -83,10 +83,10 @@ DROP PREPARE stmt;
CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','!
NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator int(10) NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
-CREATE TABLE IF NOT EXISTS online_backup ( backup_id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT 'Surrogate key for (near) duplicate entries', process_id INT UNSIGNED NOT NULL COMMENT 'The process id that operation ran as', binlog_pos INT UNSIGNED DEFAULT 0 COMMENT 'The recorded binlog position of backup/restore', binlog_file CHAR(64) COMMENT 'The recorded binlog filename at time of backup/restore', backup_state ENUM('complete', 'starting', 'validity point', 'running', 'error', 'cancel') NOT NULL COMMENT 'Status of current operation', operation ENUM('backup', 'restore') NOT NULL COMMENT 'Type of operation', error_num INT NOT NULL DEFAULT 0 COMMENT 'The error from this run 0 == none', num_objects INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'The number of objects in the backup', total_bytes BIGINT UNSIGNED COMMENT 'The size of the backup repository in bytes', validity_point_time datetime COMMENT 'The time of the validity point.', start_time datetime COMMENT 'The date/time !
of start of operation', stop_time datetime COMMENT 'The date/time of end of operation', host_or_server_name CHAR (30) COMMENT 'The server name where operation ran', username CHAR (30) COMMENT 'The user name who ran the operation', backup_file CHAR (100) COMMENT 'The name of the file', user_comment VARCHAR (200) DEFAULT NULL COMMENT 'The comment from user entered at command line', command VARCHAR (512) COMMENT 'The command used to issue operation', drivers VARCHAR (100) COMMENT 'The name of the storage engine backup drivers used in the operation') ENGINE=MYISAM;
+CREATE TABLE IF NOT EXISTS online_backup ( backup_id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT 'Surrogate key for (near) duplicate entries', process_id INT UNSIGNED NOT NULL COMMENT 'The process id that operation ran as', binlog_pos INT UNSIGNED DEFAULT 0 COMMENT 'The recorded binlog position of backup/restore', binlog_file CHAR(64) COMMENT 'The recorded binlog filename at time of backup/restore', backup_state ENUM('complete', 'starting', 'validity point', 'running', 'error', 'cancel') NOT NULL COMMENT 'Status of current operation', operation ENUM('backup', 'restore') NOT NULL COMMENT 'Type of operation', error_num INT NOT NULL DEFAULT 0 COMMENT 'The error from this run 0 == none', num_objects INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'The number of objects in the backup', total_bytes BIGINT UNSIGNED COMMENT 'The size of the backup repository in bytes', validity_point_time datetime COMMENT 'The time of the validity point.', start_time datetime COMMENT 'The date/time !
of start of operation', stop_time datetime COMMENT 'The date/time of end of operation', host_or_server_name CHAR (30) COMMENT 'The server name where operation ran', username CHAR (30) COMMENT 'The user name who ran the operation', backup_file CHAR (100) COMMENT 'The name of the file', user_comment VARCHAR (200) DEFAULT NULL COMMENT 'The comment from user entered at command line', command VARCHAR (512) COMMENT 'The command used to issue operation', drivers VARCHAR (100) COMMENT 'The name of the storage engine backup drivers used in the operation') ENGINE=MYISAM DEFAULT CHARACTER SET utf8;
-CREATE TABLE IF NOT EXISTS online_backup_progress ( backup_id BIGINT UNSIGNED NOT NULL COMMENT 'Key for online_backup table entries', object CHAR (30) NOT NULL COMMENT 'The object being operated on', start_time datetime COMMENT 'The date/time of start of operation', stop_time datetime COMMENT 'The date/time of end of operation', total_bytes BIGINT COMMENT 'The size of the object in bytes', progress BIGINT UNSIGNED COMMENT 'The number of bytes processed', error_num INT NOT NULL DEFAULT 0 COMMENT 'The error from this run 0 == none', notes CHAR(100) COMMENT 'Commentary from the backup engine') ENGINE=MYISAM;
+CREATE TABLE IF NOT EXISTS online_backup_progress ( backup_id BIGINT UNSIGNED NOT NULL COMMENT 'Key for online_backup table entries', object CHAR (30) NOT NULL COMMENT 'The object being operated on', start_time datetime COMMENT 'The date/time of start of operation', stop_time datetime COMMENT 'The date/time of end of operation', total_bytes BIGINT COMMENT 'The size of the object in bytes', progress BIGINT UNSIGNED COMMENT 'The number of bytes processed', error_num INT NOT NULL DEFAULT 0 COMMENT 'The error from this run 0 == none', notes CHAR(100) COMMENT 'Commentary from the backup engine') ENGINE=MYISAM DEFAULT CHARACTER SET utf8;
CREATE TABLE IF NOT EXISTS ndb_binlog_index (Position BIGINT UNSIGNED NOT NULL, File VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts INT UNSIGNED NOT NULL, updates INT UNSIGNED NOT NULL, deletes INT UNSIGNED NOT NULL, schemaops INT UNSIGNED NOT NULL, orig_server_id INT UNSIGNED NOT NULL, orig_epoch BIGINT UNSIGNED NOT NULL, gci INT UNSIGNED NOT NULL, PRIMARY KEY(epoch, orig_server_id, orig_epoch)) ENGINE=MYISAM;
=== modified file 'sql/backup/backup_aux.h'
--- a/sql/backup/backup_aux.h 2008-07-09 07:12:43 +0000
+++ b/sql/backup/backup_aux.h 2008-07-31 10:45:02 +0000
@@ -1,6 +1,18 @@
#ifndef _BACKUP_AUX_H
#define _BACKUP_AUX_H
+/**
+ @file
+
+ @brief Auxiliary declarations used in online backup code.
+
+ @todo Fix error detection in places marked with "FIXME: detect errors...".
+ These are places where functions or methods are called and if they can
+ report errors it should be detected and appropriate action taken. If callee
+ never reports errors or we want to ignore errors, a comment explaining this
+ should be added.
+*/
+
typedef st_plugin_int* storage_engine_ref;
// Macro which transforms plugin_ref to storage_engine_ref
@@ -131,6 +143,7 @@ void set_table_list(TABLE_LIST &tl, cons
tl.db= const_cast<char*>(tbl.db().name().ptr());
tl.lock_type= lock_type;
+ // FIXME: detect errors (if NULL returned).
tl.mdl_lock_data= mdl_alloc_lock(0, tl.db, tl.table_name, mem);
}
=== modified file 'sql/backup/backup_info.cc'
--- a/sql/backup/backup_info.cc 2008-07-09 07:12:43 +0000
+++ b/sql/backup/backup_info.cc 2008-08-05 08:04:30 +0000
@@ -4,7 +4,18 @@
Implementation of @c Backup_info class. Method @c find_backup_engine()
implements algorithm for selecting backup engine used to backup
given table.
- */
+
+ @todo Fix error detection in places marked with "FIXME: detect errors...".
+ These are places where functions or methods are called and if they can
+ report errors it should be detected and appropriate action taken. If callee
+ never reports errors or we want to ignore errors, a comment explaining this
+ should be added.
+
+ @todo Fix error logging in places marked with "FIXME: error logging...". In
+ these places it should be decided if and how the error should be shown to the
+ user. If an error message should be logged, it can happen either in the place
+ where error was detected or somewhere up the call stack.
+*/
#include "../mysql_priv.h"
@@ -306,8 +317,12 @@ Backup_info::Backup_info(Backup_restore_
bzero(m_snap, sizeof(m_snap));
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
hash_init(&ts_hash, &::my_charset_bin, 16, 0, 0,
Ts_hash_node::get_key, Ts_hash_node::free, MYF(0));
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
hash_init(&dep_hash, &::my_charset_bin, 16, 0, 0,
Dep_node::get_key, Dep_node::free, MYF(0));
@@ -319,23 +334,32 @@ Backup_info::Backup_info(Backup_restore_
snap= new Nodata_snapshot(m_ctx); // reports errors
+ // FIXME: error logging (in case snap could not be allocated).
if (!snap || !snap->is_valid())
return;
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
snapshots.push_back(snap);
snap= new CS_snapshot(m_ctx); // reports errors
+ // FIXME: error logging (in case snap could not be allocated).
if (!snap || !snap->is_valid())
return;
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
snapshots.push_back(snap);
snap= new Default_snapshot(m_ctx); // reports errors
+ // FIXME: error logging (in case snap could not be allocated).
if (!snap || !snap->is_valid())
return;
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
snapshots.push_back(snap);
m_state= CREATED;
@@ -964,9 +988,9 @@ error:
@param[in] type type of the object
@param[in] obj the object
- The object is also added to the dependency list with @c add_to_dep_list()
- method. If it is a view, its dependencies are handled first using
- @c add_view_deps().
+ The object is added both to the dependency list with @c
+ add_to_dep_list() method and to the catalogue. If it is a view, its
+ dependencies are handled first using @c add_view_deps().
@returns Pointer to @c Image_info::Dbobj instance storing information
about the object or NULL in case of error.
@@ -998,16 +1022,6 @@ Backup_info::add_db_object(Db &db, const
}
- Dbobj *o= Image_info::add_db_object(db, type, *name, pos);
-
- if (!o)
- {
- m_ctx.fatal_error(error, db.name().ptr(), name->ptr());
- return NULL;
- }
-
- o->m_obj_ptr= obj;
-
/*
Add new object to the dependency list. If it is a view, add its
dependencies first.
@@ -1026,15 +1040,6 @@ Backup_info::add_db_object(Db &db, const
return NULL;
}
- /*
- Store a pointer to the catalogue item in the dep. list node. If this node
- was a placeholder inserted into the list before, now it will be filled with
- the object we are adding to the catalogue.
- */
-
- DBUG_ASSERT(n);
- n->obj= o;
-
/*
If a new node was created, it must be added to the dependency list with
add_to_dep_list(). However, if the object is a view, we must first add
@@ -1053,6 +1058,36 @@ Backup_info::add_db_object(Db &db, const
add_to_dep_list(type, n);
}
+ /*
+ The object has now been added to the dependancy list. If it is a
+ view, all dependant objects have also been successfully added to
+ the dependency list. The object can now be added to the cataloge
+ and then be linked to from the node in the dep list. Adding to dep
+ list before adding to catalogue ensures that an object will not be
+ added to catalogue if there are problems with it's dependant
+ 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());
+ return NULL;
+ }
+
+ o->m_obj_ptr= obj;
+
+ /*
+ Store a pointer to the catalogue item in the dep. list node. If this node
+ was a placeholder inserted into the list before, now it will be filled with
+ the object we are adding to the catalogue.
+ */
+
+ DBUG_ASSERT(n);
+ n->obj= o;
+
DBUG_PRINT("backup",("Added object %s of type %d from database %s (pos=%lu)",
name->ptr(), type, db.name().ptr(), pos));
return o;
@@ -1240,8 +1275,9 @@ inline
Backup_info::Global_iterator::Global_iterator(const Image_info &info)
:Iterator(info), mode(TABLESPACES), m_it(NULL), m_obj(NULL)
{
+ // FIXME: detect errors (if NULL returned).
m_it= m_info.get_tablespaces();
- next();
+ next(); // Note: next() doesn't report errors.
}
=== modified file 'sql/backup/backup_kernel.h'
--- a/sql/backup/backup_kernel.h 2008-07-07 12:51:56 +0000
+++ b/sql/backup/backup_kernel.h 2008-08-08 17:21:31 +0000
@@ -30,7 +30,7 @@ void backup_shutdown();
Called from the big switch in mysql_execute_command() to execute
backup related statement
*/
-int execute_backup_command(THD*, LEX*);
+int execute_backup_command(THD*, LEX*, String*);
// forward declarations
@@ -66,8 +66,12 @@ class Backup_restore_ctx: public backup:
bool is_valid() const;
ulonglong op_id() const;
- Backup_info* prepare_for_backup(LEX_STRING location, const char*, bool);
- Restore_info* prepare_for_restore(LEX_STRING location, const char*);
+ Backup_info* prepare_for_backup(String *location,
+ LEX_STRING orig_loc,
+ const char*, bool);
+ Restore_info* prepare_for_restore(String *location,
+ LEX_STRING orig_loc,
+ const char*);
int do_backup();
int do_restore();
@@ -79,9 +83,11 @@ class Backup_restore_ctx: public backup:
private:
- /** Indicates if a backup/restore operation is in progress. */
- static bool is_running;
- static pthread_mutex_t run_lock; ///< To guard @c is_running flag.
+ /** @c current_op points to the @c Backup_restore_ctx for the
+ ongoing backup/restore operation. If pointer is null, no
+ operation is currently running. */
+ static Backup_restore_ctx *current_op;
+ static pthread_mutex_t run_lock; ///< To guard @c current_op.
/**
@brief State of a context object.
@@ -109,7 +115,7 @@ class Backup_restore_ctx: public backup:
backup::Image_info *m_catalog; ///< Pointer to the image catalogue object.
/** Memory allocator for backup stream library. */
- static backup::Mem_allocator *mem_alloc;
+ backup::Mem_allocator *mem_alloc;
int prepare(LEX_STRING location);
void disable_fkey_constraints();
=== modified file 'sql/backup/data_backup.cc'
--- a/sql/backup/data_backup.cc 2008-07-07 12:51:56 +0000
+++ b/sql/backup/data_backup.cc 2008-07-31 10:45:02 +0000
@@ -7,6 +7,17 @@
drivers and protocols to create snapshot of the data stored in the tables being
backed up.
+ @todo Fix error detection in places marked with "FIXME: detect errors...".
+ These are places where functions or methods are called and if they can
+ report errors it should be detected and appropriate action taken. If callee
+ never reports errors or we want to ignore errors, a comment explaining this
+ should be added.
+
+ @todo Fix error logging in places marked with "FIXME: error logging...". In
+ these places it should be decided if and how the error should be shown to the
+ user. If an error message should be logged, it can happen either in the place
+ where error was detected or somewhere up the call stack.
+
@todo Implement better scheduling strategy in Scheduler::step
@todo Add error reporting in the scheduler and elsewhere
@todo If an error from driver is ignored (and operation retried) leave trace
@@ -459,6 +470,8 @@ int write_table_data(THD* thd, Backup_in
if (init_size > max_init_size)
max_init_size= init_size;
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
inactive.push_back(p);
}
}
@@ -579,6 +592,8 @@ int write_table_data(THD* thd, Backup_in
Save binlog information for point in time recovery on restore.
*/
if (mysql_bin_log.is_open())
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
mysql_bin_log.get_current_log(&binlog_pos);
/*
@@ -766,12 +781,14 @@ int Scheduler::step()
break;
case backup_state::DONE:
+ // FIXME: detect errors if reported.
p->end();
case backup_state::ERROR:
- remove_pump(p);
+ remove_pump(p); // Note: never errors.
if (res)
cancel_backup(); // we hit an error - bail out
+ // Note: cancel_backup() never errors.
break;
default: break;
@@ -903,8 +920,8 @@ void Scheduler::cancel_backup()
while (m_count && m_pumps)
{
Pump_iterator p(*this);
- p->cancel();
- remove_pump(p);
+ p->cancel(); // Note: even if cancel() errors, we ignore it.
+ remove_pump(p); // Note: never errors.
}
cancelled= TRUE;
@@ -923,7 +940,7 @@ int Scheduler::prepare()
{
if (it->prepare())
{
- cancel_backup();
+ cancel_backup(); // Note: never errors.
return ERROR;
}
if (it->state == backup_state::PREPARING)
@@ -946,7 +963,7 @@ int Scheduler::lock()
for (Pump_iterator it(*this); it; ++it)
if (it->lock())
{
- cancel_backup();
+ cancel_backup(); // Note: never errors.
return ERROR;
}
@@ -965,7 +982,7 @@ int Scheduler::unlock()
{
if (it->unlock())
{
- cancel_backup();
+ cancel_backup(); // Note: never errors.
return ERROR;
}
if (it->state == backup_state::FINISHING)
@@ -990,6 +1007,7 @@ Backup_pump::Backup_pump(Snapshot_info &
{
DBUG_ASSERT(snap.m_num > 0);
m_buf.data= NULL;
+ // FIXME: detect errors if reported.
bitmap_init(&m_closed_streams,
NULL,
1 + snap.table_count(),
@@ -1229,6 +1247,8 @@ int Backup_pump::pump(size_t *howmuch)
if (m_buf.size > 0)
mode= WRITING;
else
+ // FIXME: detect errors (perhaps ensure that drop_buf never errors).
+ // FIXME: error logging.
m_bw.drop_buf(m_buf);
break;
@@ -1247,6 +1267,8 @@ int Backup_pump::pump(size_t *howmuch)
state= backup_state::DONE;
case BUSY:
+ // FIXME: detect errors (perhaps ensure that drop_buf never errors).
+ // FIXME: error logging.
m_bw.drop_buf(m_buf);
m_buf_head=NULL; // thus a new request will be made
}
@@ -1502,6 +1524,8 @@ int restore_table_data(THD *thd, Restore
bad_drivers.append(",");
bad_drivers.append(info.m_snap[n]->name());
}
+ // FIXME: detect errors.
+ // FIXME: error logging.
drv[n]->free();
}
@@ -1520,6 +1544,8 @@ int restore_table_data(THD *thd, Restore
if (!drv[n])
continue;
+ // FIXME: detect errors.
+ // FIXME: error logging (perhaps we don't want to report errors here).
drv[n]->free();
}
=== modified file 'sql/backup/image_info.cc'
--- a/sql/backup/image_info.cc 2008-06-18 14:09:34 +0000
+++ b/sql/backup/image_info.cc 2008-07-31 10:45:02 +0000
@@ -8,6 +8,16 @@
@brief Implements @c Image_info class and friends.
+ @todo Fix error detection in places marked with "FIXME: detect errors...".
+ These are places where functions or methods are called and if they can
+ report errors it should be detected and appropriate action taken. If callee
+ never reports errors or we want to ignore errors, a comment explaining this
+ should be added.
+
+ @todo Fix error logging in places marked with "FIXME: error logging...". In
+ these places it should be decided if and how the error should be shown to the
+ user. If an error message should be logged, it can happen either in the place
+ where error was detected or somewhere up the call stack.
*/
namespace backup {
@@ -15,6 +25,7 @@ namespace backup {
Image_info::Image_info()
:data_size(0), m_table_count(0), m_dbs(16, 16), m_ts_map(16,16)
{
+ // FIXME: detect errors if reported.
init_alloc_root(&mem_root, 4 * 1024, 0);
/* initialize st_bstream_image_header members */
@@ -295,14 +306,15 @@ Image_info::add_table(Db &db, const ::St
if (!t)
return NULL;
- if (snap.add_table(*t, pos))
+ if (snap.add_table(*t, pos)) // reports errors
return NULL;
+ // FIXME: error logging.
if (db.add_table(*t))
return NULL;
if (!snap.m_num)
- snap.m_num= add_snapshot(snap);
+ snap.m_num= add_snapshot(snap); // reports errors
if (!snap.m_num)
return NULL;
=== modified file 'sql/backup/image_info.h'
--- a/sql/backup/image_info.h 2008-07-07 12:51:56 +0000
+++ b/sql/backup/image_info.h 2008-07-31 10:45:02 +0000
@@ -1,6 +1,15 @@
#ifndef CATALOG_H_
#define CATALOG_H_
+/**
+ @file
+
+ @todo Fix error logging in places marked with "FIXME: error logging...". In
+ these places it should be decided if and how the error should be shown to the
+ user. If an error message should be logged, it can happen either in the place
+ where error was detected or somewhere up the call stack.
+*/
+
#include <si_objects.h>
#include <backup_stream.h> // for st_bstream_* types
#include <backup/backup_aux.h> // for Map template
@@ -802,6 +811,7 @@ void Image_info::save_binlog_pos(const :
inline
Image_info::Db_iterator* Image_info::get_dbs() const
{
+ // FIXME: error logging (in case allocation fails).
return new Db_iterator(*this);
}
@@ -809,6 +819,7 @@ Image_info::Db_iterator* Image_info::get
inline
Image_info::Ts_iterator* Image_info::get_tablespaces() const
{
+ // FIXME: error logging (in case allocation fails).
return new Ts_iterator(*this);
}
@@ -816,6 +827,7 @@ Image_info::Ts_iterator* Image_info::get
inline
Image_info::Dbobj_iterator* Image_info::get_db_objects(const Db &db) const
{
+ // FIXME: error logging (in case allocation fails).
return new Dbobj_iterator(*this, db);
}
=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc 2008-07-09 08:19:03 +0000
+++ b/sql/backup/kernel.cc 2008-08-08 17:21:31 +0000
@@ -19,7 +19,8 @@
{
Backup_restore_ctx context(thd); // create context instance
- Backup_info *info= context.prepare_for_backup(location); // prepare for backup
+ Backup_info *info= context.prepare_for_backup(location,
+ orig_loc); // prepare for backup
// select objects to backup
info->add_all_dbs();
@@ -41,7 +42,8 @@
{
Backup_restore_ctx context(thd); // create context instance
- Restore_info *info= context.prepare_for_restore(location); // prepare for restore
+ Restore_info *info= context.prepare_for_restore(location,
+ orig_loc); // prepare for restore
context.do_restore(); // perform restore
@@ -50,15 +52,22 @@
} // if code jumps here, context destructor will do the clean-up automatically
@endcode
+ @todo Fix error detection in places marked with "FIXME: detect errors...".
+ These are places where functions or methods are called and if they can
+ report errors it should be detected and appropriate action taken. If callee
+ never reports errors or we want to ignore errors, a comment explaining this
+ should be added.
+
+ @todo Fix error logging in places marked with "FIXME: error logging...". In
+ these places it should be decided if and how the error should be shown to the
+ user. If an error message should be logged, it can happen either in the place
+ where error was detected or somewhere up the call stack.
+
@todo Use internal table name representation when passing tables to
backup/restore drivers.
@todo Handle other types of meta-data in Backup_info methods.
@todo Handle item dependencies when adding new items.
@todo Handle other kinds of backup locations (far future).
-
- @note This comment was added to show Jorgen and Oystein how to push patches
- into the team tree - please remove it if you see it. Second version of the
- patch, to show how to collapse/re-edit csets.
*/
#include "../mysql_priv.h"
@@ -111,7 +120,9 @@ static int send_reply(Backup_restore_ctx
/**
Call backup kernel API to execute backup related SQL statement.
- @param lex results of parsing the statement.
+ @param[IN] thd current thread object reference.
+ @param[IN] lex results of parsing the statement.
+ @param[IN] backupdir value of the backupdir variable from server.
@note This function sends response to the client (ok, result set or error).
@@ -119,7 +130,7 @@ static int send_reply(Backup_restore_ctx
*/
int
-execute_backup_command(THD *thd, LEX *lex)
+execute_backup_command(THD *thd, LEX *lex, String *backupdir)
{
int res= 0;
@@ -127,6 +138,7 @@ execute_backup_command(THD *thd, LEX *le
DBUG_ASSERT(thd && lex);
DEBUG_SYNC(thd, "before_backup_command");
+
using namespace backup;
Backup_restore_ctx context(thd); // reports errors
@@ -134,13 +146,25 @@ execute_backup_command(THD *thd, LEX *le
if (!context.is_valid())
DBUG_RETURN(send_error(context, ER_BACKUP_CONTEXT_CREATE));
+ /*
+ Check backupdir for validity. This is needed since we cannot trust
+ that the path is still valid. Access could have changed or the
+ folders in the path could have been moved, deleted, etc.
+ */
+ if (backupdir->length() && my_access(backupdir->c_ptr(), (F_OK|W_OK)))
+ {
+ context.fatal_error(ER_BACKUP_BACKUPDIR, backupdir->c_ptr());
+ DBUG_RETURN(send_error(context, ER_BACKUP_BACKUPDIR, backupdir->c_ptr()));
+ }
+
switch (lex->sql_command) {
case SQLCOM_BACKUP:
{
// prepare for backup operation
- Backup_info *info= context.prepare_for_backup(lex->backup_dir, thd->query,
+ Backup_info *info= context.prepare_for_backup(backupdir, lex->backup_dir,
+ thd->query,
lex->backup_compression);
// reports errors
@@ -185,7 +209,8 @@ execute_backup_command(THD *thd, LEX *le
case SQLCOM_RESTORE:
{
- Restore_info *info= context.prepare_for_restore(lex->backup_dir, thd->query);
+ Restore_info *info= context.prepare_for_restore(backupdir, lex->backup_dir,
+ thd->query);
if (!info || !info->is_valid())
DBUG_RETURN(send_error(context, ER_BACKUP_RESTORE_PREPARE));
@@ -271,17 +296,31 @@ int send_reply(Backup_restore_ctx &conte
/*
Send field list.
*/
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
field_list.push_back(new Item_empty_string(STRING_WITH_LEN("backup_id")));
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
/*
Send field data.
*/
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
protocol->prepare_for_resend();
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
llstr(context.op_id(), buf);
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
protocol->store(buf, system_charset_info);
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
protocol->write();
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
my_eof(context.thd());
DBUG_RETURN(0);
}
@@ -323,15 +362,14 @@ class Mem_allocator
// static members
-bool Backup_restore_ctx::is_running= FALSE;
+Backup_restore_ctx *Backup_restore_ctx::current_op= NULL;
pthread_mutex_t Backup_restore_ctx::run_lock;
-backup::Mem_allocator *Backup_restore_ctx::mem_alloc= NULL;
Backup_restore_ctx::Backup_restore_ctx(THD *thd)
:Logger(thd), m_state(CREATED), m_thd_options(thd->options),
m_error(0), m_path(NULL), m_remove_loc(FALSE), m_stream(NULL),
- m_catalog(NULL), m_tables_locked(FALSE)
+ m_catalog(NULL), mem_alloc(NULL), m_tables_locked(FALSE)
{
/*
Check for progress tables.
@@ -344,6 +382,7 @@ Backup_restore_ctx::~Backup_restore_ctx(
{
close();
+ delete mem_alloc;
delete m_catalog;
delete m_stream;
}
@@ -366,8 +405,12 @@ int Backup_restore_ctx::prepare(LEX_STRI
// Prepare error reporting context.
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
mysql_reset_errors(m_thd, 0);
m_thd->no_warnings_for_error= FALSE;
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
save_errors();
@@ -387,8 +430,8 @@ int Backup_restore_ctx::prepare(LEX_STRI
pthread_mutex_lock(&run_lock);
- if (!is_running)
- is_running= TRUE;
+ if (!current_op)
+ current_op= this;
else
fatal_error(ER_BACKUP_RUNNING);
@@ -399,6 +442,11 @@ int Backup_restore_ctx::prepare(LEX_STRI
// check if location is valid (we assume it is a file path)
+ /*
+ For this error to work correctly, we need to check original
+ file specified by the user rather than the path formed
+ using the backupdir.
+ */
bool bad_filename= (location.length == 0);
/*
@@ -408,7 +456,7 @@ int Backup_restore_ctx::prepare(LEX_STRI
#if defined(__WIN__) || defined(__EMX__)
bad_filename = bad_filename || check_if_legal_filename(location.str);
-
+
#endif
if (bad_filename)
@@ -446,7 +494,8 @@ int Backup_restore_ctx::prepare(LEX_STRI
/**
Prepare for backup operation.
- @param[in] location path to the file where backup image should be stored
+ @param[in] backupdir path to the file where backup image should be stored
+ @param[in] orig_loc path as specified on command line for backup image
@param[in] query BACKUP query starting the operation
@param[in] with_compression backup image compression switch
@@ -461,7 +510,9 @@ int Backup_restore_ctx::prepare(LEX_STRI
is performed using @c do_backup() method.
*/
Backup_info*
-Backup_restore_ctx::prepare_for_backup(LEX_STRING location, const char *query,
+Backup_restore_ctx::prepare_for_backup(String *backupdir,
+ LEX_STRING orig_loc,
+ const char *query,
bool with_compression)
{
using namespace backup;
@@ -469,7 +520,7 @@ Backup_restore_ctx::prepare_for_backup(L
if (m_error)
return NULL;
- if (Logger::init(BACKUP, location, query))
+ if (Logger::init(BACKUP, orig_loc, query))
{
fatal_error(ER_BACKUP_LOGGER_INIT);
return NULL;
@@ -482,16 +533,16 @@ Backup_restore_ctx::prepare_for_backup(L
Do preparations common to backup and restore operations. After call
to prepare() all meta-data changes are blocked.
*/
- if (prepare(location))
+ if (prepare(orig_loc))
return NULL;
- backup::String path(location);
-
/*
Open output stream.
*/
-
- Output_stream *s= new Output_stream(*this, path, with_compression);
+ Output_stream *s= new Output_stream(*this,
+ backupdir,
+ orig_loc,
+ with_compression);
m_stream= s;
if (!s)
@@ -502,7 +553,11 @@ Backup_restore_ctx::prepare_for_backup(L
if (!s->open())
{
- fatal_error(ER_BACKUP_WRITE_LOC, path.ptr());
+ /*
+ For this error, use the actual value returned instead of the
+ path complimented with backupdir.
+ */
+ fatal_error(ER_BACKUP_WRITE_LOC, orig_loc.str);
return NULL;
}
@@ -531,7 +586,8 @@ Backup_restore_ctx::prepare_for_backup(L
/**
Prepare for restore operation.
- @param[in] location path to the file where backup image is stored
+ @param[in] backupdir path to the file where backup image is stored
+ @param[in] orig_loc path as specified on command line for backup image
@param[in] query RESTORE query starting the operation
@returns Pointer to a @c Restore_info instance containing catalogue of the
@@ -540,14 +596,16 @@ Backup_restore_ctx::prepare_for_backup(L
@note This function reports errors.
*/
Restore_info*
-Backup_restore_ctx::prepare_for_restore(LEX_STRING location, const char *query)
+Backup_restore_ctx::prepare_for_restore(String *backupdir,
+ LEX_STRING orig_loc,
+ const char *query)
{
using namespace backup;
if (m_error)
return NULL;
- if (Logger::init(RESTORE, location, query))
+ if (Logger::init(RESTORE, orig_loc, query))
{
fatal_error(ER_BACKUP_LOGGER_INIT);
return NULL;
@@ -560,15 +618,14 @@ Backup_restore_ctx::prepare_for_restore(
Do preparations common to backup and restore operations. After this call
changes of meta-data are blocked.
*/
- if (prepare(location))
+ if (prepare(orig_loc))
return NULL;
/*
Open input stream.
*/
- backup::String path(location);
- Input_stream *s= new Input_stream(*this, path);
+ Input_stream *s= new Input_stream(*this, backupdir, orig_loc);
m_stream= s;
if (!s)
@@ -579,7 +636,11 @@ Backup_restore_ctx::prepare_for_restore(
if (!s->open())
{
- fatal_error(ER_BACKUP_READ_LOC, path.ptr());
+ /*
+ For this error, use the actual value returned instead of the
+ path complimented with backupdir.
+ */
+ fatal_error(ER_BACKUP_READ_LOC, orig_loc.str);
return NULL;
}
@@ -669,9 +730,13 @@ int Backup_restore_ctx::lock_tables_for_
backup::Image_info::Table *tbl= snap->get_table(t);
DBUG_ASSERT(tbl); // All tables should be present in the catalogue.
+ // FIXME: detect errors. Don't assert here but report error instead.
+ // FIXME: error logging.
TABLE_LIST *ptr= backup::mk_table_list(*tbl, TL_WRITE, m_thd->mem_root);
- DBUG_ASSERT(ptr); // FIXME: report error instead
+ DBUG_ASSERT(ptr);
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
tables= backup::link_table_list(*ptr, tables);
tbl->m_table= ptr;
}
@@ -733,8 +798,10 @@ int Backup_restore_ctx::close()
time_t when= my_time(0);
// If auto commit is turned off, be sure to commit the transaction
- // TODO: move it to the big switch, case: MYSQLCOM_BACKUP?
-
+ /*
+ Note: this code needs to be refactored (see BUG#38261). When refactoring
+ make sure that errors are detected and reported.
+ */
if (m_thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
{
ha_autocommit_or_rollback(m_thd, 0);
@@ -743,10 +810,13 @@ int Backup_restore_ctx::close()
// unlock tables if they are still locked
+ // FIXME: detect errors if reported.
unlock_tables();
// unfreeze meta-data
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
obs::ddl_blocker_disable();
// restore thread options
@@ -756,20 +826,23 @@ int Backup_restore_ctx::close()
// close stream
if (m_stream)
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
m_stream->close();
if (m_catalog)
- m_catalog->save_end_time(when);
+ m_catalog->save_end_time(when); // Note: no errors.
// destroy backup stream's memory allocator (this frees memory)
delete mem_alloc;
mem_alloc= NULL;
- // deregister this operation
-
+ // deregister this operation if it was running
pthread_mutex_lock(&run_lock);
- is_running= FALSE;
+ if (current_op == this) {
+ current_op= NULL;
+ }
pthread_mutex_unlock(&run_lock);
/*
@@ -827,6 +900,8 @@ int Backup_restore_ctx::do_backup()
DEBUG_SYNC(m_thd, "before_backup_meta");
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
report_stats_pre(info);
DBUG_PRINT("backup",("Writing preamble"));
@@ -852,6 +927,8 @@ int Backup_restore_ctx::do_backup()
DBUG_RETURN(m_error);
}
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
report_stats_post(info);
DBUG_PRINT("backup",("Backup done."));
@@ -880,6 +957,7 @@ int Backup_restore_ctx::restore_triggers
DBUG_ASSERT(m_catalog);
+ // FIXME: detect errors (when dbit==NULL). Perhaps just assert.
Image_info::Iterator *dbit= m_catalog->get_dbs();
Image_info::Obj *obj;
List<Image_info::Obj> events;
@@ -891,6 +969,7 @@ int Backup_restore_ctx::restore_triggers
while ((obj= (*dbit)++))
{
+ // FIXME: detect errors (when it==NULL). Perhaps just assert.
Image_info::Iterator *it=
m_catalog->get_db_objects(*static_cast<Image_info::Db*>(obj));
@@ -899,6 +978,8 @@ int Backup_restore_ctx::restore_triggers
case BSTREAM_IT_EVENT:
DBUG_ASSERT(obj->m_obj_ptr);
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
events.push_back(obj);
break;
@@ -961,11 +1042,14 @@ int Backup_restore_ctx::do_restore()
Input_stream &s= *static_cast<Input_stream*>(m_stream);
Restore_info &info= *static_cast<Restore_info*>(m_catalog);
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
report_stats_pre(info);
DBUG_PRINT("restore", ("Restoring meta-data"));
- disable_fkey_constraints();
+ // FIXME: detect errors if reported.
+ disable_fkey_constraints(); // reports errors
if (read_meta_data(info, s))
{
@@ -973,6 +1057,7 @@ int Backup_restore_ctx::do_restore()
DBUG_RETURN(m_error);
}
+ // FIXME: detect errors.
s.next_chunk();
DBUG_PRINT("restore",("Restoring table data"));
@@ -983,7 +1068,11 @@ int Backup_restore_ctx::do_restore()
It should be fixed inside object services implementation and then the
following line should be removed.
*/
+ // FIXME: detect errors.
+ // FIXME: error logging.
close_thread_tables(m_thd);
+ // FIXME: detect errors.
+ // FIXME: error logging.
m_thd->main_da.reset_diagnostics_area();
if (lock_tables_for_restore()) // reports errors
@@ -992,6 +1081,7 @@ int Backup_restore_ctx::do_restore()
// Here restore drivers are created to restore table data
err= restore_table_data(m_thd, info, s); // reports errors
+ // FIXME: detect errors if reported.
unlock_tables();
if (err)
@@ -1004,7 +1094,7 @@ int Backup_restore_ctx::do_restore()
creation of these objects will fail.
*/
- if (restore_triggers_and_events())
+ if (restore_triggers_and_events()) // reports errors
DBUG_RETURN(ER_BACKUP_RESTORE);
DBUG_PRINT("restore",("Done."));
@@ -1021,9 +1111,15 @@ int Backup_restore_ctx::do_restore()
It should be fixed inside object services implementation and then the
following line should be removed.
*/
+ // FIXME: detect errors.
+ // FIXME: error logging.
close_thread_tables(m_thd);
+ // FIXME: detect errors.
+ // FIXME: error logging.
m_thd->main_da.reset_diagnostics_area();
+ // FIXME: detect errors if reported.
+ // FIXME: error logging.
report_stats_post(info);
DBUG_RETURN(0);
@@ -1135,9 +1231,10 @@ bstream_byte* bstream_alloc(unsigned lon
{
using namespace backup;
- DBUG_ASSERT(Backup_restore_ctx::mem_alloc);
+ DBUG_ASSERT(Backup_restore_ctx::current_op
+ && Backup_restore_ctx::current_op->mem_alloc);
- return (bstream_byte*)Backup_restore_ctx::mem_alloc->alloc(size);
+ return (bstream_byte*)Backup_restore_ctx::current_op->mem_alloc->alloc(size);
}
/**
@@ -1147,8 +1244,9 @@ extern "C"
void bstream_free(bstream_byte *ptr)
{
using namespace backup;
- if (Backup_restore_ctx::mem_alloc)
- Backup_restore_ctx::mem_alloc->free(ptr);
+ if (Backup_restore_ctx::current_op
+ && Backup_restore_ctx::current_op->mem_alloc)
+ Backup_restore_ctx::current_op->mem_alloc->free(ptr);
}
/**
=== modified file 'sql/backup/stream.cc'
--- a/sql/backup/stream.cc 2008-07-02 11:27:17 +0000
+++ b/sql/backup/stream.cc 2008-08-08 17:21:31 +0000
@@ -190,9 +190,11 @@ extern "C" int stream_read(void *instanc
}
-Stream::Stream(Logger &log, const ::String &name, int flags)
- :m_path(name), m_flags(flags), m_block_size(0), m_log(log)
+Stream::Stream(Logger &log, ::String *backupdir,
+ LEX_STRING orig_loc, int flags)
+ :m_flags(flags), m_block_size(0), m_log(log)
{
+ prepare_path(backupdir, orig_loc);
bzero(&stream, sizeof(stream));
bzero(&buf, sizeof(buf));
bzero(&mem, sizeof(mem));
@@ -201,6 +203,150 @@ Stream::Stream(Logger &log, const ::Stri
state= CLOSED;
}
+/**
+ Make a relative path.
+
+ This method takes the backupdir and the path specified on the backup command
+ (orig_loc) and forms a combined path. It walks the backupdir from the right
+ and the orig_loc from the left to position the paths for concatenation. Output
+ is written to new_path.
+
+ @param[OUT] new_path The newly combined path + file name.
+ @param[IN] orig_loc The path + file name specified in the backup command.
+ @param[IN] backupdir The backupdir system variable value.
+
+ For example, if backupdir = '/dev/tmp' and orig_log = '../backup.bak', the
+ combined path is = '/dev/backup.bak'.
+
+ @returns
+ 0 if success
+ 1 if cannot be combined. Note: m_path is set to '' when this occurs to
+ trigger error in call stack.
+*/
+int Stream::make_relative_path(char *new_path,
+ char *orig_loc,
+ ::String *backupdir)
+{
+ char fixed_base[FN_LEN];
+ char fixed_rel[FN_LEN];
+ cleanup_dirname(fixed_base, backupdir->c_ptr());
+ cleanup_dirname(fixed_rel, orig_loc);
+ char *rel;
+ char *base= fixed_base;
+ bool done= FALSE;
+ char *found= fixed_rel;
+ int j= backupdir->length() - 1;
+ new_path[0]= 0; // initialize the new path to an empty string
+
+ /*
+ For each '../' in orig_loc, move the pointer to the right for rel.
+ For each '../' in orig_loc, move pointer to the left for base.
+ */
+ while (!done)
+ {
+ rel= found; // save last known position
+ // find location of next level in relative path
+ found= strstr(found, FN_PARENTDIR);
+ if (found)
+ {
+ found+= 2; // move past '..\'
+ if (base[j] == FN_LIBCHAR)
+ j--; // move past last '\'
+ if (j == 0) // We are trying to move too far down the path
+ return 1;
+ /*
+ Look for the next level down.
+ */
+ while ((base[j] != FN_LIBCHAR) && j)
+ j--;
+ }
+ else
+ done= TRUE;
+ }
+ strcpy (new_path, base);
+ strcpy (new_path + j, rel);
+ return 0;
+}
+
+/**
+ Prepare path for access.
+
+ This method takes the backupdir and the file name specified on the backup
+ command (orig_loc) and forms a combined path + file name as follows:
+
+ 1. If orig_loc has a relative path, make it relative to backupdir
+ 2. If orig_loc has a hard path, use it.
+ 3. If orig_loc has no path, append to backupdir
+
+ @param[IN] backupdir The backupdir system variable value.
+ @param[IN] orig_loc The path + file name specified in the backup command.
+
+ @returns 0
+*/
+int Stream::prepare_path(::String *backupdir,
+ LEX_STRING orig_loc)
+{
+ int path_len= 0;
+
+ /*
+ Prepare the path using the backupdir iff no relative path
+ or no hard path included.
+
+ Relative paths are formed from the backupdir system variable.
+ */
+ if (is_prefix(orig_loc.str, FN_PARENTDIR))
+ {
+ /*
+ Case 1: Backup image file name has relative path.
+ Make relative to backupdir.
+
+ Example BACKUP DATATBASE ... TO '../monthly/dec.bak'
+ If backupdir = '/dev/daily/backup' then the
+ calculated path becomes
+ '/dev/monthly/backup/dec.bak'
+ */
+ char new_path[FN_LEN];
+ if (make_relative_path(new_path, orig_loc.str, backupdir))
+ m_path.length(0);
+ path_len= strlen(new_path) + 1;
+ m_path.alloc(path_len);
+ m_path.length(0);
+ m_path.append(new_path);
+ }
+ else if (!test_if_hard_path(orig_loc.str))
+ {
+ /*
+ Case 2: Backup image file name has hard path.
+
+ Example BACKUP DATATBASE ... TO '/dev/dec.bak'
+ If backupdir = '/dev/daily/backup' then the
+ calculated path becomes
+ '/dev/dec.bak'
+ */
+ path_len=backupdir->length() + orig_loc.length + 1;
+ m_path.alloc(path_len);
+ fn_format(m_path.c_ptr(), orig_loc.str, backupdir->c_ptr(), "",
+ MY_UNPACK_FILENAME);
+ }
+ else
+ {
+ /*
+ Case 3: Backup image file name has no path.
+
+ Example BACKUP DATATBASE ... TO 'week2.bak'
+ If backupdir = '/dev/weekly/backup' then the
+ calculated path becomes
+ '/dev/weekly/week2.bak'
+ */
+ path_len= orig_loc.length + 1;
+ m_path.alloc(path_len);
+ m_path.length(0);
+ m_path.append(orig_loc.str);
+ }
+ m_path.length(path_len);
+ return 0;
+}
+
bool Stream::open()
{
close();
@@ -228,9 +374,10 @@ bool Stream::rewind()
}
-Output_stream::Output_stream(Logger &log, const ::String &name,
+Output_stream::Output_stream(Logger &log, ::String *backupdir,
+ LEX_STRING orig_loc,
bool with_compression)
- :Stream(log, name, 0)
+ :Stream(log, backupdir, orig_loc, 0)
{
m_with_compression= with_compression;
stream.write= stream_write;
@@ -414,8 +561,9 @@ bool Output_stream::rewind()
}
-Input_stream::Input_stream(Logger &log, const ::String &name)
- :Stream(log, name, O_RDONLY)
+Input_stream::Input_stream(Logger &log, ::String *backupdir,
+ LEX_STRING orig_loc)
+ :Stream(log, backupdir, orig_loc, O_RDONLY)
{
m_with_compression= false;
stream.read= stream_read;
=== modified file 'sql/backup/stream.h'
--- a/sql/backup/stream.h 2008-06-26 16:20:30 +0000
+++ b/sql/backup/stream.h 2008-08-08 17:21:31 +0000
@@ -92,7 +92,7 @@ class Stream: public fd_stream
protected:
- Stream(Logger&, const ::String&, int);
+ Stream(Logger&, ::String *, LEX_STRING, int);
String m_path;
int m_flags; ///< flags used when opening the file
@@ -101,6 +101,15 @@ class Stream: public fd_stream
friend int stream_write(void*, bstream_blob*, bstream_blob);
friend int stream_read(void*, bstream_blob*, bstream_blob);
+
+private:
+
+ int make_relative_path(char *new_path,
+ char *orig_loc,
+ ::String *backupdir);
+ int prepare_path(::String *backupdir,
+ LEX_STRING orig_loc);
+
};
/// Used to write to backup stream.
@@ -109,7 +118,7 @@ class Output_stream:
{
public:
- Output_stream(Logger&, const ::String&, bool);
+ Output_stream(Logger&, ::String *, LEX_STRING, bool);
bool open();
void close();
@@ -127,7 +136,7 @@ class Input_stream:
{
public:
- Input_stream(Logger&, const ::String &name);
+ Input_stream(Logger&, ::String *, LEX_STRING);
bool open();
void close();
=== modified file 'sql/backup/stream_v1.c'
--- a/sql/backup/stream_v1.c 2008-05-14 00:35:24 +0000
+++ b/sql/backup/stream_v1.c 2008-08-11 10:41:41 +0000
@@ -1555,14 +1555,25 @@ int bstream_wr_item_def(backup_stream *s
blob data;
int ret=BSTREAM_OK;
- if (bcat_get_item_create_query(cat,item,&query) == BSTREAM_OK)
+ ret= bcat_get_item_create_query(cat,item,&query);
+ if (ret == BSTREAM_OK)
flags |= BSTREAM_FLAG_HAS_CREATE_STMT;
+ else if (ret == BSTREAM_ERROR)
+ goto wr_error;
- if (bcat_get_item_create_data(cat,item,&data) == BSTREAM_OK)
+ // bcat_get_item_create_data not in use yet.
+ /*
+ ret= bcat_get_item_create_data(cat,item,&data);
+ if (ret == BSTREAM_OK)
flags |= BSTREAM_FLAG_HAS_EXTRA_DATA;
-
+ else if (ret == BSTREAM_ERROR)
+ goto wr_error;
+ */
+
ret= bstream_wr_meta_item(s,kind,flags,item);
-
+ if (ret == BSTREAM_ERROR)
+ goto wr_error;
+
/* save create query and/or create data */
if (flags & BSTREAM_FLAG_HAS_EXTRA_DATA)
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2008-07-09 07:12:43 +0000
+++ b/sql/mysqld.cc 2008-08-08 17:21:31 +0000
@@ -1364,6 +1364,7 @@ void clean_up(bool print_message)
my_free(sys_init_slave.value, MYF(MY_ALLOW_ZERO_PTR));
my_free(sys_var_general_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
my_free(sys_var_slow_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(sys_var_backupdir.value, MYF(MY_ALLOW_ZERO_PTR));
free_tmpdir(&mysql_tmpdir_list);
#ifdef HAVE_REPLICATION
my_free(slave_load_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
@@ -5793,6 +5794,8 @@ struct my_option my_long_options[] =
"Creating and dropping stored procedures alters ACLs. Disable with --skip-automatic-sp-privileges.",
(uchar**) &sp_automatic_privileges, (uchar**) &sp_automatic_privileges,
0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ {"backupdir", 'B', "Path used to store backup data.", (uchar**) &sys_var_backupdir.value,
+ (uchar**) &sys_var_backupdir.value, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"basedir", 'b',
"Path to installation directory. All paths are usually resolved relative to this.",
(uchar**) &mysql_home_ptr, (uchar**) &mysql_home_ptr, 0, GET_STR, REQUIRED_ARG,
@@ -7916,6 +7919,21 @@ mysqld_get_one_option(int optid,
case 'l':
opt_log=1;
break;
+ case 'B':
+ {
+ /*
+ Check if directory exists and we have permission to create file and
+ write to file.
+ */
+ if (my_access(argument, (F_OK|W_OK)))
+ {
+ sql_print_warning("The path specified for the variable backupdir cannot"
+ " be accessed or is invalid. ref:'%s'\n", argument);
+ }
+ sys_var_backupdir.value= my_strdup(argument, MYF(0));
+ sys_var_backupdir.value_length= strlen(sys_var_backupdir.value);
+ break;
+ }
case 'h':
strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1);
/* Correct pointer set by my_getopt (for embedded library) */
@@ -8625,6 +8643,16 @@ static void fix_paths(void)
convert_dirname(language,language,NullS);
(void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
(void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home);
+
+ /*
+ Set backupdir if datadir set on command line but not otherwise set.
+ */
+ if (!sys_var_backupdir.value)
+ {
+ sys_var_backupdir.value= my_strdup(mysql_real_data_home, MYF(0));
+ sys_var_backupdir.value_length= strlen(mysql_real_data_home);
+ }
+
(void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home);
(void) my_load_path(opt_plugin_dir, opt_plugin_dir_ptr ? opt_plugin_dir_ptr :
get_relative_path(PLUGINDIR), mysql_home);
=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc 2008-07-09 07:12:43 +0000
+++ b/sql/set_var.cc 2008-08-08 17:21:31 +0000
@@ -149,6 +149,9 @@ static bool sys_update_general_log_path(
static void sys_default_general_log_path(THD *thd, enum_var_type type);
static bool sys_update_slow_log_path(THD *thd, set_var * var);
static void sys_default_slow_log_path(THD *thd, enum_var_type type);
+static int sys_check_backupdir(THD *thd, set_var *var);
+static bool sys_update_backupdir(THD *thd, set_var * var);
+static void sys_default_backupdir(THD *thd, enum_var_type type);
/*
Variable definition list
@@ -779,6 +782,15 @@ sys_var_str sys_var_slow_log_path(&vars,
static sys_var_log_output sys_var_log_output_state(&vars, "log_output", &log_output_options,
&log_output_typelib, 0);
+/*
+ Create the backupdir dynamic variable.
+*/
+sys_var_str sys_var_backupdir(&vars, "backupdir",
+ sys_check_backupdir,
+ sys_update_backupdir,
+ sys_default_backupdir,
+ 0);
+
/*
Additional variables (not derived from sys_var class, not accessible as
@@ -2613,6 +2625,140 @@ uchar *sys_var_log_output::value_ptr(THD
return (uchar*) thd->strmake(tmp.ptr(), length);
}
+/*
+ Functions for backupdir variable.
+*/
+
+/**
+ Set the default for the backupdir
+
+ @param[IN] buff Buffer to use for making string.
+
+ @returns pointer to string (buff)
+*/
+char *make_default_backupdir(char *buff)
+{
+ strmake(buff, mysql_data_home, FN_REFLEN-5);
+ return buff;
+}
+
+/**
+ Check the backupdir value for validity.
+
+ This method ensures the users is specifying a valid path
+ for the backupdir. Validity in this case means the path
+ is accessible to the user.
+
+ @param[IN] thd Current thread context.
+ @param[IN] var The new value set in set_var structure.
+
+ @returns 0
+*/
+static int sys_check_backupdir(THD *thd, set_var *var)
+{
+ char path[FN_REFLEN], buff[FN_REFLEN];
+ MY_STAT f_stat;
+ String str(buff, sizeof(buff), system_charset_info), *res;
+ const char *log_file_str;
+ size_t path_length;
+
+ if (!(res= var->value->val_str(&str)))
+ goto err;
+
+ log_file_str= res->c_ptr();
+ bzero(&f_stat, sizeof(MY_STAT));
+
+ /* Get dirname of the file path. */
+ (void) dirname_part(path, log_file_str, &path_length);
+
+ /* Dirname is empty if file path is relative. */
+ if (!path_length)
+ return 0;
+
+ /*
+ Check if directory exists and we have permission to create file and
+ write to file.
+ */
+ if (my_access(path, (F_OK|W_OK)))
+ goto err;
+
+ return 0;
+
+err:
+ /*
+ We print a warning if backupdir is invalid but set it anyway.
+ */
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_BACKUP_BACKUPDIR, ER(ER_BACKUP_BACKUPDIR),
+ var->value->str_value.c_ptr());
+ return 0;
+}
+
+/**
+ Update the backupdir variable
+
+ This method is used to change the backupdir variable.
+
+ @param[IN] thd Current thread context.
+ @param[IN] var The new value set in set_var structure.
+
+ @returns 0 valid, 1 invalid.
+*/
+static bool sys_update_backupdir(THD *thd, set_var * var)
+{
+ char buff[FN_REFLEN];
+ char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
+ bool result= 0;
+ uint str_length= (var ? var->value->str_value.length() : 0);
+
+ if (!old_value)
+ {
+ old_value= make_default_backupdir(buff);
+ str_length= strlen(old_value);
+ }
+ if (!(res= my_strndup(old_value, str_length, MYF(MY_FAE+MY_WME))))
+ {
+ result= 1;
+ goto err;
+ }
+
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ logger.lock_exclusive();
+ old_value= sys_var_backupdir.value;
+ sys_var_backupdir.value= res;
+ sys_var_backupdir.value_length= str_length;
+ logger.unlock();
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+
+ if (my_access(sys_var_backupdir.value, (F_OK|W_OK)))
+ goto err;
+
+ return result;
+
+err:
+ /*
+ We print a warning if backupdir is invalid but set it anyway.
+ */
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_BACKUP_BACKUPDIR, ER(ER_BACKUP_BACKUPDIR),
+ var->value->str_value.c_ptr());
+ return result;
+}
+
+/**
+ Set the default value for the backupdir variable
+
+ This method is used to reset the backupdir variable to the
+ default by calling the update method without a path.
+
+ @param[IN] thd Current thread context.
+ @param[IN] type Ignored (needed for api).
+*/
+static void sys_default_backupdir(THD *thd, enum_var_type type)
+{
+ sys_update_backupdir(thd, 0);
+}
+
/*****************************************************************************
Functions to handle SET NAMES and SET CHARACTER SET
=== modified file 'sql/set_var.h'
--- a/sql/set_var.h 2008-07-09 07:12:43 +0000
+++ b/sql/set_var.h 2008-08-08 17:21:31 +0000
@@ -1345,7 +1345,8 @@ CHARSET_INFO *get_old_charset_by_name(co
uchar* find_named(I_List<NAMED_LIST> *list, const char *name, uint length,
NAMED_LIST **found);
-extern sys_var_str sys_var_general_log_path, sys_var_slow_log_path;
+extern sys_var_str sys_var_general_log_path, sys_var_slow_log_path,
+ sys_var_backupdir;
/* key_cache functions */
KEY_CACHE *get_key_cache(LEX_STRING *cache_name);
=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt 2008-07-09 07:12:43 +0000
+++ b/sql/share/errmsg.txt 2008-08-08 17:21:31 +0000
@@ -6372,3 +6372,5 @@ ER_BACKUP_OBTAIN_NAME_LOCK_FAILED
eng "Restore failed to obtain the name locks on the tables."
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"
=== modified file 'sql/si_objects.cc'
--- a/sql/si_objects.cc 2008-07-09 07:12:43 +0000
+++ b/sql/si_objects.cc 2008-08-11 10:41:41 +0000
@@ -1769,8 +1769,11 @@ bool TableObj::do_serialize(THD *thd, St
/*
Open the view and its base tables or views
*/
- if (open_normal_and_derived_tables(thd, table_list, 0))
- DBUG_RETURN(FALSE);
+ if (open_normal_and_derived_tables(thd, table_list, 0)) {
+ close_thread_tables(thd);
+ thd->lex->select_lex.table_list.empty();
+ DBUG_RETURN(TRUE);
+ }
/*
Setup view specific variables and settings
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2008-07-14 14:56:49 +0000
+++ b/sql/sql_parse.cc 2008-08-08 17:21:31 +0000
@@ -41,7 +41,7 @@
@defgroup Runtime_Environment Runtime Environment
@{
*/
-int execute_backup_command(THD*,LEX*);
+int execute_backup_command(THD*, LEX*, String*);
/* Used in error handling only */
#define SP_TYPE_STRING(LP) \
@@ -2166,10 +2166,21 @@ mysql_execute_command(THD *thd)
#else
{
/*
+ Create a string from the backupdir system variable and pass
+ to backup system.
+ */
+ String backupdir;
+
+ backupdir.alloc(sys_var_backupdir.value_length);
+ backupdir.set_ascii(sys_var_backupdir.value,
+ sys_var_backupdir.value_length);
+ backupdir.length(sys_var_backupdir.value_length);
+
+ /*
Note: execute_backup_command() sends a correct response to the client
(either ok, result set or error message).
- */
- if (execute_backup_command(thd,lex))
+ */
+ if (execute_backup_command(thd, lex, &backupdir))
goto error;
break;
}
=== modified file 'storage/myisam/mi_dynrec.c'
--- a/storage/myisam/mi_dynrec.c 2008-07-09 07:12:43 +0000
+++ b/storage/myisam/mi_dynrec.c 2008-07-23 12:46:33 +0000
@@ -1742,7 +1742,7 @@ int _mi_read_rnd_dynamic_record(MI_INFO
{ /* Check if changed */
info_read=1;
info->rec_cache.seek_not_done=1;
- if (mi_state_info_read_dsk(share->kfile,&share->state,1))
+ if (mi_state_info_read_dsk(share->kfile, &share->state, 1, 0))
goto panic;
}
if (filepos >= info->state->data_file_length)
=== modified file 'storage/myisam/mi_examine_log.c'
--- a/storage/myisam/mi_examine_log.c 2008-07-08 20:18:10 +0000
+++ b/storage/myisam/mi_examine_log.c 2008-07-23 12:46:33 +0000
@@ -860,13 +860,9 @@ static int mi_close_care_state(MI_INFO *
if (!update_index_on_close)
{
MYISAM_SHARE *share;
- my_bool old_myisam_single_user;
share= info->s;
- old_myisam_single_user= myisam_single_user;
- myisam_single_user= FALSE;
- (void) mi_state_info_read_dsk(share->kfile, &share->state, 1);
- myisam_single_user= old_myisam_single_user;
+ (void) mi_state_info_read_dsk(share->kfile, &share->state, 1, 1);
}
return mi_close(info);
}
=== modified file 'storage/myisam/mi_locking.c'
--- a/storage/myisam/mi_locking.c 2008-07-09 07:12:43 +0000
+++ b/storage/myisam/mi_locking.c 2008-07-23 12:46:33 +0000
@@ -159,7 +159,7 @@ int mi_lock_database(MI_INFO *info, int
error=my_errno;
break;
}
- if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
+ if (mi_state_info_read_dsk(share->kfile, &share->state, 1, 0))
{
error=my_errno;
(void) my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
@@ -204,7 +204,7 @@ int mi_lock_database(MI_INFO *info, int
}
if (!share->r_locks)
{
- if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
+ if (mi_state_info_read_dsk(share->kfile, &share->state, 1, 0))
{
error=my_errno;
(void) my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
@@ -415,7 +415,7 @@ int _mi_readinfo(register MI_INFO *info,
if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
info->lock_wait | MY_SEEK_NOT_DONE))
DBUG_RETURN(1);
- if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
+ if (mi_state_info_read_dsk(share->kfile, &share->state, 1, 0))
{
int error= my_errno ? my_errno : HA_ERR_FILE_TOO_SHORT;
(void) my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
=== modified file 'storage/myisam/mi_open.c'
--- a/storage/myisam/mi_open.c 2008-07-09 07:12:43 +0000
+++ b/storage/myisam/mi_open.c 2008-07-23 12:46:33 +0000
@@ -1048,11 +1048,40 @@ uchar *mi_state_info_read(uchar *ptr, MI
}
-uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead)
+/**
+ Read state info from file.
+
+ @param[in] file index file descriptor
+ @param[in,out] state state info to update from file
+ @param[in] pRead if to use my_pread() instaed of my_read()
+ @param[in] force force read
+
+ @return status
+ @retval 0 ok
+ @retval 1 error
+
+ Normally this function does not read the state info from file if
+ 'myisam_single_user' is true. This means that mysqld is the only
+ program that works on the table files. No other program modifies the
+ files. Hence the in-memory state is expected to be current.
+
+ If there are other programs tampering with the files, mysqld must be
+ started with --external-locking. This makes 'myisam_single_user'
+ false. In this case this function does indeed read the state from
+ disk.
+
+ In cases like restore, we modify the table files directly,
+ bypassing the MyISAM interface. We do this inside of mysqld, so
+ --external-locking need not be specified. We support this case by the
+ 'force' parameter.
+*/
+
+uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead,
+ my_bool force)
{
uchar buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
- if (!myisam_single_user)
+ if (!myisam_single_user || force)
{
if (pRead)
{
=== modified file 'storage/myisam/myisam_backup_engine.cc'
--- a/storage/myisam/myisam_backup_engine.cc 2008-07-14 15:33:03 +0000
+++ b/storage/myisam/myisam_backup_engine.cc 2008-07-23 12:46:33 +0000
@@ -1758,7 +1758,6 @@ result_t Table_restore::close()
{
MI_INFO *mi_info;
MYISAM_SHARE *share;
- my_bool old_myisam_single_user;
mi_info= mi_open(file_name.ptr(), O_RDWR, HA_OPEN_FOR_REPAIR);
if (mi_info == NULL)
@@ -1766,14 +1765,8 @@ result_t Table_restore::close()
share= mi_info->s;
DBUG_PRINT("myisam_backup", ("share data_file: %lu",
(ulong) share->state.state.data_file_length));
- old_myisam_single_user= myisam_single_user;
- myisam_single_user= FALSE;
- if (mi_state_info_read_dsk(share->kfile,&share->state,1))
- {
- myisam_single_user= old_myisam_single_user;
+ if (mi_state_info_read_dsk(share->kfile, &share->state, 1, 1))
goto err;
- }
- myisam_single_user= old_myisam_single_user;
DBUG_PRINT("myisam_backup", ("share data_file: %lu",
(ulong) share->state.state.data_file_length));
/*
=== modified file 'storage/myisam/myisamdef.h'
--- a/storage/myisam/myisamdef.h 2008-07-09 08:19:03 +0000
+++ b/storage/myisam/myisamdef.h 2008-07-23 12:46:33 +0000
@@ -799,7 +799,8 @@ uint mi_state_info_write(MYISAM_SHARE *s
MI_STATE_INFO *state, uint pWrite);
uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state);
int mi_remap_file_and_write_state_for_unlock(MI_INFO *info);
-uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead);
+uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead,
+ my_bool force);
uint mi_base_info_write(File file, MI_BASE_INFO *base);
uchar *mi_n_base_info_read(uchar *ptr, MI_BASE_INFO *base);
int mi_keyseg_write(File file, const HA_KEYSEG *keyseg);
| Thread |
|---|
| • bzr commit into mysql-6.0-backup branch (cbell:2671) Bug#33836 Bug#34867Bug#34902 Bug#35230 Bug#36795 Bug#38108 WL#4384 | Chuck Bell | 11 Aug |