--source include/have_debug_sync.inc
--source include/not_embedded.inc

# This test checks that re-created events or triggers are not fired during
# RESTORE operation.
#
# Author: Rafal Somla
let $MYSQLD_BACKUPDIR= `select @@backupdir`;
--disable_warnings
--error 0,1
--remove_file $MYSQLD_BACKUPDIR/db.bak
--enable_warnings

SET GLOBAL event_scheduler=off;
SET DEBUG_SYNC = 'RESET';

# We need a separate connection to measure timing for RESTORE command. This is
# because of BUG#35806: time stops in a thread executing RESTORE command.

connect(con1, localhost, root,,);
connect(con2, localhost, root,,);

--connection con1

# Events and triggers will insert entries into a log table so that we can see
# if they have fired.

--echo Creating log table.

--disable_warnings
DROP TABLE IF EXISTS test.logt;
--enable_warnings

CREATE TABLE test.logt(ts timestamp, db char(8), msg text);

--echo Creating database db and its objects.

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

CREATE DATABASE db;
USE db;

CREATE TABLE t1 (a int); 
INSERT INTO t1 VALUES (0),(1),(2),(3),(4),(5),(6);

delimiter ||;

CREATE EVENT ev ON SCHEDULE EVERY 1 second DO 
BEGIN
  INSERT INTO test.logt(db, msg) VALUES ('db','Db event fired!');
END;
||

CREATE PROCEDURE trg_msg(a int)
BEGIN
    INSERT INTO test.logt(db, msg) VALUES ('db','Db trigger fired!');
END;
||

CREATE TRIGGER after_ins AFTER INSERT ON t1 FOR EACH ROW 
CALL trg_msg(NEW.a);
||

CREATE TRIGGER after_upd AFTER UPDATE ON t1 FOR EACH ROW 
CALL trg_msg(NEW.a);
||

CREATE TRIGGER after_del AFTER DELETE ON t1 FOR EACH ROW 
CALL trg_msg(OLD.a);
||

CREATE TRIGGER before_ins BEFORE INSERT ON t1 FOR EACH ROW 
CALL trg_msg(NEW.a);
||

CREATE TRIGGER before_upd BEFORE UPDATE ON t1 FOR EACH ROW 
CALL trg_msg(NEW.a);
||

# Create a trigger with the same name as an event to test that backup is
# able to handle that.  (Bug#38810)
CREATE TRIGGER ev BEFORE DELETE ON t1 FOR EACH ROW 
CALL trg_msg(OLD.a);
||

# Create an event and trigger in test database to see that they are not
# affected by RESTORE of another database.

USE test||

--disable_warnings
DROP EVENT IF EXISTS ev||
DROP TABLE IF EXISTS t1||
DROP TRIGGER IF EXISTS trg||
--enable_warnings

CREATE EVENT ev ON SCHEDULE EVERY 1 second DO
BEGIN
  INSERT INTO test.logt(db, msg) VALUES ('test','Test event fired!');
END;
||

CREATE TABLE t1 (a int)||

CREATE TRIGGER trg AFTER INSERT ON t1 FOR EACH ROW
BEGIN
  INSERT INTO test.logt(db, msg) VALUES ('test','Test trigger fired');   
END;
||

delimiter ;||

--echo Backing-up database db and dropping it.

--replace_column 1 #
BACKUP DATABASE db TO 'db.bak';
DROP DATABASE db;

--connection con1

--echo con1: clearing log table and starting RESTORE operation.
--echo con1: RESTORE will pause after restoring table data.

# Synchronization point 'restore_table_data_before_end' is inside RESTORE code,
# after restore drivers have finished their job but before they have been shoot
# down.

SET DEBUG_SYNC = 'after_backup_start_restore SIGNAL started WAIT_FOR continue';
SET DEBUG_SYNC = 'restore_table_data_before_end SIGNAL waiting WAIT_FOR finish';
DELETE FROM test.logt;
--send RESTORE FROM 'db.bak'

--connection con2

SET DEBUG_SYNC = 'now WAIT_FOR started';
--echo Enabling event scheduler.
SET GLOBAL event_scheduler=on;
# Give it a second to start
--sleep 1

--echo Get BACKUP going.
# Record the time when RESTORE has started.
SELECT now() INTO @start;
SET DEBUG_SYNC = 'now SIGNAL continue';

--echo con2: checking that there are no triggers and events at the end of RESTORE execution.

# Wait until RESTORE reaches the moment when all table data is restored.
SET DEBUG_SYNC = 'now WAIT_FOR waiting';
# There should be no triggers and no events at this moment (they are created
# after table data is restored)
--query_vertical SHOW TRIGGERS FROM db
--query_vertical SHOW EVENTS IN db

--echo con2: activating trigger in test database.
INSERT INTO test.t1 VALUES (1);

--echo con2: ensuring that RESTORE takes at least 3 secs.

# This is so that db.ev event has chance to fire if it is not correctly handled
# (e.g. enabled during table data restore).
--sleep 4
SET DEBUG_SYNC = 'now SIGNAL finish';

--connection con1

--echo con1: finishing RESTORE operation.
--replace_column 1 #
--reap
SET GLOBAL event_scheduler=off;

--connection con2

-- echo con2: checking that RESTORE took more than 2 secs.

SELECT timediff(now(),@start) > 3;

--echo Checking that objects have been restored.

USE db;

SHOW TABLES IN db;
SELECT count(*) FROM db.t1;
--replace_column 9 #
--query_vertical SHOW TRIGGERS FROM db
--replace_column 9 #
--query_vertical SHOW EVENTS IN db

--echo Checking that no db event or trigger fired during RESTORE.

# There should be no entries in the log table from the time when RESTORE
# was running (but there could be entries inserted by event firing *after*
# RESTORE has completed). We know that RESTORE took at least 4 sec and we
# take 3 sec window from the beginning of the operation. This is enough
# to see db.ev in case it fired during RESTORE operation (this event is sheduled
# to fire every second).

SELECT * FROM test.logt WHERE db = 'db' AND timediff(ts,@start) < 3;

--echo Checking that test event and trigger could fire.

# Checking that the test trigger has fired during RESTORE.
SELECT count(*) > 0 FROM test.logt 
WHERE db = 'test'
AND msg LIKE '%trigger fired%'
AND timediff(ts,@start) < 3;

# Checking that the test event has fired during RESTORE.
SELECT count(*) > 0 FROM test.logt 
WHERE db = 'test'
AND msg LIKE '%event fired%'
AND timediff(ts,@start) < 3;

--echo Cleaning up.
SET DEBUG_SYNC = 'RESET';
DROP EVENT test.ev;
DROP TRIGGER test.trg;
DROP TABLE test.logt;
DROP TABLE test.t1;
DROP DATABASE db;

--remove_file $MYSQLD_BACKUPDIR/db.bak
