--source include/have_innodb.inc
--source include/have_blackhole.inc
--source include/not_embedded.inc
--source include/have_debug_sync.inc
--source include/have_log_bin.inc

SET DEBUG_SYNC= 'RESET';

connect (backup,localhost,root,,);
connect (breakpoints,localhost,root,,);

connection backup;

--disable_warnings
DROP DATABASE IF EXISTS db1;
DROP DATABASE IF EXISTS db2;
DROP DATABASE IF EXISTS db3;

let $MYSQLD_BACKUPDIR= `select @@backupdir`;
--error 0,1
remove_file $MYSQLD_BACKUPDIR/bup_default.bak;
--enable_warnings

CREATE DATABASE db1;
CREATE DATABASE db2 CHARACTER SET=utf8;
CREATE DATABASE db3 COLLATE latin1_bin;

USE db1;

CREATE TABLE `building` (
  `dir_code` char(4),
  `building` char(6)
) DEFAULT CHARSET=latin1;

#
# Dumping data for table `building`
#

INSERT INTO `building` VALUES ('N41','1300'),('N01','1453'),('M00','1000'),('N41','1301'),('N41','1305');


#
# Table structure for table `directorate`
#

CREATE TABLE `directorate` (
  `dir_code` char(4),
  `dir_name` char(30),
  `dir_head_id` char(9)
) DEFAULT CHARSET=latin1;

#
# Dumping data for table `directorate`
#

INSERT INTO `directorate` VALUES ('N41','Development','333445555'),('N01','Human Resources','123654321'),('M00','Management','333444444');

USE db2;

#
# Table structure for table `staff`
#

CREATE TABLE `staff` (
  `id` char(9),
  `first_name` char(20),
  `mid_name` char(20),
  `last_name` char(30),
  `sex` char(1),
  `salary` int(11),
  `mgr_id` char(9)
) DEFAULT CHARSET=latin1;

#
# Dumping data for table `staff`
#

INSERT INTO `staff` VALUES ('333445555','John','Q','Smith','M',30000,'333444444'),('123763153','William','E','Walters','M',25000,'123654321'),('333444444','Alicia','F','St.Cruz','F',25000,NULL),('921312388','Goy','X','Hong','F',40000,'123654321'),('800122337','Rajesh','G','Kardakarna','M',38000,'333445555'),('820123637','Monty','C','Smythe','M',38000,'333445555'),('830132335','Richard','E','Jones','M',38000,'333445555'),('333445665','Edward','E','Engles','M',25000,'333445555'),('123654321','Beware','D','Borg','F',55000,'333444444'),('123456789','Wilma','N','Maxima','F',43000,'333445555');

#
# Table structure for table `tasking`
#

CREATE TABLE `tasking` (
  `id` char(9),
  `project_number` char(9),
  `hours_worked` double(10,2)
) ENGINE=blackhole DEFAULT CHARSET=latin1;

#
# Dumping data for table `tasking`
#

INSERT INTO `tasking` VALUES ('333445555','405',23),('123763153','405',33.5),('921312388','601',44),('800122337','300',13),('820123637','300',9.5),('830132335','401',8.5),('333445555','300',11),('921312388','500',13),('800122337','300',44),('820123637','401',500.5),('830132335','400',12),('333445665','600',300.25),('123654321','607',444.75),('123456789','300',1000);

#
# Get a lock to check for locking thread in process list
# Note that this portion of the test is designed to merely
# test that the locking thread code is correctly displayed
# in the process list and not a complete test of the locking
# thread code.
#
connection backup;
--echo backup: Activate synchronization points for BACKUP.
--echo Depending on the driver used, one of the sync points is used,
--echo and the result differs in PROCESSLIST state and info.
SET DEBUG_SYNC= 'default_locking_thread_added SIGNAL bup_thread_added
                 WAIT_FOR finish';
SET DEBUG_SYNC= concat(lower(@@storage_engine), '_locking_thread_added SIGNAL bup_thread_added WAIT_FOR finish');
--echo backup: Send the backup command.
send BACKUP DATABASE db1,db2 TO 'test.ba';

# get the lock and wait until lock is identified in process list
connection breakpoints;
--echo breakpoints: Wait for BACKUP to reach its synchronization point.
SET DEBUG_SYNC= 'now WAIT_FOR bup_thread_added';

--echo breakpoints: Sending finish signal to wake BACKUP.
SET DEBUG_SYNC= 'now SIGNAL finish';

# reattach to backup job
connection backup;
--replace_column 1 #
reap;

# get backup_id of the BACKUP operation. 
SELECT MAX(backup_id) FROM mysql.backup_history INTO @bid;

# store VP time and binlog position

SELECT validity_point_time FROM mysql.backup_history
WHERE backup_id = @bid INTO @vp_time;
SELECT binlog_file FROM mysql.backup_history
WHERE backup_id = @bid INTO @vp_file;
SELECT binlog_pos FROM mysql.backup_history
WHERE backup_id = @bid INTO @vp_pos;

DROP DATABASE db1;
DROP DATABASE db2;

#Disabled until SHOW commands are implemented.
#SHOW BACKUP 'test.ba';

USE mysql;

# wait few seconds so that restore time != backup time
--sleep 2

--replace_column 1 #
RESTORE FROM 'test.ba';

# determine id of RESTORE operation
SELECT MAX(backup_id) FROM mysql.backup_history INTO @bid;

remove_file $MYSQLD_BACKUPDIR/test.ba;

SHOW CREATE DATABASE db1;
SHOW CREATE DATABASE db2;
SHOW CREATE DATABASE db3;

USE db1;
SHOW TABLES;

CHECK TABLE building EXTENDED;
CHECK TABLE directorate EXTENDED;

SELECT * FROM building;
SELECT * FROM directorate;


USE db2;
SHOW TABLES;

CHECK TABLE staff EXTENDED;

SELECT * FROM staff;
SHOW CREATE TABLE tasking;

# check that VP info was correctly read and reported

SELECT validity_point_time = @vp_time, 
       binlog_file = @vp_file, 
       binlog_pos = @vp_pos
FROM mysql.backup_history
WHERE backup_id = @bid; 

DROP DATABASE db1;
DROP DATABASE db2;
DROP DATABASE db3;
SET DEBUG_SYNC= 'RESET';

#
# Check that PTR data (such as VP time and binlog positon) is correctly stored and read
# when there are no tables to backup (BUG#40262). 
#

--error 0,1
--remove_file $MYSQLD_BACKUPDIR/db1.bkp
CREATE DATABASE db1;

--replace_column 1 #
BACKUP DATABASE db1 TO 'db1.bkp';
# get backup_id of the BACKUP operation. 
SELECT MAX(backup_id) FROM mysql.backup_history INTO @bid;

# store VP time and binlog position

SELECT validity_point_time FROM mysql.backup_history
WHERE backup_id = @bid INTO @vp_time;
SELECT binlog_file FROM mysql.backup_history
WHERE backup_id = @bid INTO @vp_file;
SELECT binlog_pos FROM mysql.backup_history
WHERE backup_id = @bid INTO @vp_pos;

DROP DATABASE db1;

# wait few seconds so that restore time != backup time
--sleep 2

--replace_column 1 #
RESTORE FROM 'db1.bkp';
# determine id of RESTORE operation
SELECT MAX(backup_id) FROM mysql.backup_history INTO @bid;

# check that VP info was correctly read and reported

SELECT validity_point_time = @vp_time,
       binlog_file = @vp_file,
       binlog_pos = @vp_pos
FROM mysql.backup_history
WHERE backup_id = @bid; 

DROP DATABASE db1;
--remove_file $MYSQLD_BACKUPDIR/db1.bkp


#
# This test is for the default and snapshot online backup drivers
#

connection backup;

--disable_warnings
DROP DATABASE IF EXISTS bup_default;
--enable_warnings

CREATE DATABASE bup_default;

# Create tables and load with data.

CREATE TABLE bup_default.wide (
  `a` int(11) NOT NULL AUTO_INCREMENT,
  `b` char(255) DEFAULT NULL,
  `c` char(255) DEFAULT NULL,
  `d` char(255) DEFAULT NULL,
  `e` char(255) DEFAULT NULL,
  `f` char(255) DEFAULT NULL,
  `g` char(255) DEFAULT NULL,
  `h` char(255) DEFAULT NULL,
  `i` char(255) DEFAULT NULL,
  `j` char(255) DEFAULT NULL,
  `k` char(255) DEFAULT NULL,
  `l` char(255) DEFAULT NULL,
  `m` char(255) DEFAULT NULL,
  `n` char(255) DEFAULT NULL,
  `o` char(255) DEFAULT NULL,
  `p` char(255) DEFAULT NULL,
  `q` TEXT,
  PRIMARY KEY (`a`)
) ENGINE=INNODB DEFAULT CHARSET=latin1;

CREATE TABLE bup_default.t1 (a int) engine=innodb;
CREATE TABLE bup_default.t2 (a int);
CREATE TABLE bup_default.t1_blob (a int, b text) engine=innodb;

# Insert some data.

INSERT INTO bup_default.wide VALUES (
NULL,
"This is column b pass 01",
"This is column c pass 01",
"This is column d pass 01",
"This is column e pass 01",
"This is column f pass 01",
"This is column g pass 01",
"This is column h pass 01",
"This is column i pass 01",
"This is column j pass 01",
"This is column k pass 01",
"This is column l pass 01",
"This is column m pass 01",
"This is column n pass 01",
"This is column o pass 01",
"This is column p pass 01",
"Running the server in debug:

linux:/home/Chuck # mysqld-debug -u root --debug=d,enter,exit:t:F:L:g:O,/tmp/mys
qld.trace &
[2] 7492
[1]   Done                    kwrite /tmp/mysqld.trace
linux:/home/Chuck # 060601 21:18:45  InnoDB: Started; log sequence number 0 4640
3
060601 21:18:45 [Note] mysqld-debug: ready for connections.
Version: '5.1.9-beta-debug-log'  socket: '/var/lib/mysql/mysql.sock'  port: 3306
  MySQL Community Server - Debug (GPL)
060601 21:18:57 [Note] mysqld-debug: Normal shutdown

060601 21:18:59  InnoDB: Starting shutdown...
060601 21:19:01  InnoDB: Shutdown completed; log sequence number 0 46403
060601 21:19:01 [Note] mysqld-debug: Shutdown complete

Running the client:

Chuck@linux:~> mysql -uroot -p
Enter password:");

INSERT INTO bup_default.t1 VALUES (1);
INSERT INTO bup_default.t1 VALUES (2);
INSERT INTO bup_default.t1 VALUES (3);
INSERT INTO bup_default.t1 VALUES (4);
INSERT INTO bup_default.t2 VALUES (1);
INSERT INTO bup_default.t2 VALUES (2);
INSERT INTO bup_default.t2 VALUES (3);
INSERT INTO bup_default.t2 VALUES (4);

INSERT INTO bup_default.t1_blob VALUES (1,"Short text will fit in buffer.");
INSERT INTO bup_default.t1_blob VALUES (2,"Replication Failover
--------------------
One of the greatest advantages of MySQL replication is the ability to failover in the event of a server crash. More specifically, if you need to take your master server offline you can promote one of your slaves as a master and thereby minimize the interruption to your users.

Promoting a Slave to a Master
-----------------------------
When your master fails beyond repair, you can quickly replace it with your slave and reestablish service to your databases and applications. The process for promoting a slave to a master involves taking the master offline (if not already), flushing the logs and safely shutting down the slave, then restarting the slave to run as the master. A simplified process is shown below.

1. Lock the tables on your master.
2. Record the location of the binlog on the master for point in time recovery (if needed).
3. Flush the logs on the slave.
4. Shutdown the master.
5. Shutdown the slave you want to promote.
6. Restart the slave specifying the startup options for the master.

Notes
-----
Your configuration may require slightly differing steps in the process to match your environment. Things to consider include how the applications connect to the server, where the data is store (NAS or other detached storage), and the mode of replication among your master and slave(s).

Remember to keep the server_id the same as it was when the promoted slave was a slave!

If you have applications that use embedded hostnames or IP addresses in their connections to the master, you have two choices; 1) you can change the slave's hostname and IP to that of the master and restart the server, or 2) you can redirect your clients to the promoted slave.

Failover and Invoked Objects
----------------------------
For most applications, the failover sequence described above will get you a viable master and return your database system to service. If you use invoked objects, specifically events, the promotion of the slave to a master involves some additional steps.

If you are unsure if you have any events that are replicated, you can issue the following command on the slave (you need to have privileges to run the show commands):

SHOW EVENTS WHERE STATUS = 'SLAVESIDE_DISABLED';

This query will list all of the events on the slave that have been replicated FROM the master. You will also see a column named ORIGINATOR that lists the server_id of the originating master. Together with the STATUS column, you can quickly determine which events need to be activated on the newly promoted slave.

To turn the events on, you can create and run the following stored procedure:
NORMAL END!");

# Show the data

SELECT * FROM bup_default.t1;
SELECT * FROM bup_default.t2;
SELECT COUNT(*) FROM bup_default.t1_blob;
--query_vertical SELECT * FROM bup_default.t1_blob;
SELECT COUNT(*) FROM bup_default.wide;
--query_vertical SELECT * FROM bup_default.wide;

--replace_column 1 #
BACKUP DATABASE bup_default TO "bup_default.bak";

# Now restore the database and then check to make sure the data is there.

DROP DATABASE bup_default;

--replace_column 1 #
--query_vertical RESTORE FROM "bup_default.bak"

# Show the data

SELECT * FROM bup_default.t1;
SELECT * FROM bup_default.t2;
SELECT COUNT(*) FROM bup_default.t1_blob;
--query_vertical SELECT * FROM bup_default.t1_blob;
SELECT COUNT(*) FROM bup_default.wide;
--query_vertical SELECT * FROM bup_default.wide;

#
# Test that backup/restore operations work correctly regardless of the
# current setting of sql_mode (BUG#33571)
#

# Change sql_mode to ANSI and see if it is possible to restore and backup 
# a database with non-default sql_mode.

SET sql_mode=ansi;
SHOW VARIABLES LIKE 'sql_mode';

DROP DATABASE bup_default;

--replace_column 1 #
RESTORE FROM 'bup_default.bak';

# See that sql_mode was not modified by RESTORE operation.

SHOW VARIABLES LIKE 'sql_mode';

# Check that database was restored.

SHOW TABLES IN bup_default;
SHOW CREATE TABLE bup_default.t1;
SELECT * FROM bup_default.t1;
SELECT * FROM bup_default.t2;
SELECT COUNT(*) FROM bup_default.t1_blob;
SELECT COUNT(*) FROM bup_default.wide;

remove_file $MYSQLD_BACKUPDIR/bup_default.bak;
--replace_column 1 #
BACKUP DATABASE bup_default TO 'bup_default.bak';

# See that sql_mode was not modified by BACKUP operation.

SHOW VARIABLES LIKE 'sql_mode';


# We have backed up a database when sql_mode was ANSI. Change
# the mode back to default and see that we can correctly restore.

SET sql_mode='';
SHOW VARIABLES LIKE 'sql_mode';

DROP DATABASE bup_default;

--replace_column 1 #
RESTORE FROM 'bup_default.bak';

# See that sql_mode was not modified by RESTORE operation.

SHOW VARIABLES LIKE 'sql_mode';

# Check that database was restored.

SHOW TABLES IN bup_default;
SHOW CREATE TABLE bup_default.t1;
SELECT * FROM bup_default.t1;
SELECT * FROM bup_default.t2;
SELECT COUNT(*) FROM bup_default.t1_blob;
SELECT COUNT(*) FROM bup_default.wide;

#
# BUG#35249 : Test backup when rows are deleted
#

--echo create the database
CREATE DATABASE bup_delete;

--echo create a table and populate it
CREATE TABLE bup_delete.me(id int, ccode varchar(20)) ENGINE=MEMORY;
INSERT INTO bup_delete.me VALUES (1,'aa'),(2,'bb'),(3,'cc'),(4,'dd');

--echo show the data
SELECT * FROM bup_delete.me;

--echo delete a row
DELETE FROM bup_delete.me WHERE ccode='cc';

--echo do backup
--replace_column 1 #
BACKUP DATABASE bup_delete TO 'bup_delete.bak';

--echo show the data
SELECT * FROM bup_delete.me;

--echo do restore
--replace_column 1 #
RESTORE FROM 'bup_delete.bak' OVERWRITE;

--echo show the data
SELECT * FROM bup_delete.me;

DROP TABLE bup_default.t1;
DROP TABLE bup_default.t2;
DROP TABLE bup_default.t1_blob;
DROP TABLE bup_default.wide;

#
# BUG#33573 : Check timestamp field values on restore.
#

--echo Create table with timestamp and populate.
CREATE TABLE bup_default.time_t1 (a INT, b TIMESTAMP);

--echo Set known timestamp value and insert a row
SET TIMESTAMP= UNIX_TIMESTAMP('2008-06-10 17:00:00');
INSERT INTO bup_default.time_t1 VALUES (1, NULL);

--echo Set known timestamp value and insert a row
SET TIMESTAMP= UNIX_TIMESTAMP('2008-06-11 08:15:21');
INSERT INTO bup_default.time_t1 VALUES (2, NULL);

--echo Set known timestamp value and insert a row
SET TIMESTAMP= UNIX_TIMESTAMP('2008-06-12 00:00:59');
INSERT INTO bup_default.time_t1 VALUES (3, NULL);

--echo Show the data
SELECT * FROM bup_default.time_t1;

--echo Backup the database.
--replace_column 1 #
BACKUP DATABASE bup_default TO 'bup_default_timestamp.bak';

--echo Restore the database.
--replace_column 1 #
RESTORE FROM 'bup_default_timestamp.bak' OVERWRITE;

--echo Show data after restore (timestamp should be same as above).
SELECT * FROM bup_default.time_t1;

--echo Set known timestamp value and insert a row
SET TIMESTAMP= UNIX_TIMESTAMP('2008-06-13 23:59:59');
INSERT INTO bup_default.time_t1 VALUES (4, NULL);

--echo Set known timestamp value and insert a row
SET TIMESTAMP= UNIX_TIMESTAMP('2008-04-01 00:00:01');
INSERT INTO bup_default.time_t1 VALUES (5, NULL);

--echo Show data that was added after restore
SELECT * FROM bup_default.time_t1;

--disable_warnings
DROP DATABASE IF EXISTS bup_delete;
DROP DATABASE IF EXISTS bup_default;
--enable_warnings

--echo # 
--echo # Bug#38294 - Backup fails if no database selected.
--echo #

CREATE DATABASE bup_usedb;
CREATE FUNCTION bup_usedb.f1() RETURNS INT RETURN (SELECT 1);

# The SHOW TABLES below is used to ensure that no database is
# selected. If something changes to the other tests in this file so
# that SHOW TABLES does not fail as expected, the following
# create/use/drop sequence will result in the expected bahavior of no
# database selected.

# CREATE DATABASE dbuseme;
# USE dbuseme;
# DROP DATABASE dbuseme;

--error ER_NO_DB_ERROR
SHOW TABLES;

# Calling backup without calling 'use db' first
--replace_column 1 #
BACKUP DATABASE bup_usedb TO 'bup_usedb.bak';

DROP DATABASE bup_usedb;

--echo #
--echo # Cleanup
--echo #

--remove_file $MYSQLD_BACKUPDIR/bup_usedb.bak
--remove_file $MYSQLD_BACKUPDIR/bup_delete.bak
--remove_file $MYSQLD_BACKUPDIR/bup_default_timestamp.bak
--remove_file $MYSQLD_BACKUPDIR/bup_default.bak
--error 0,1
--remove_file $MYSQLD_BACKUPDIR/test.bak

