###############################################################################
# Bug#76727: SLAVE ASSERTION IN UNPACK_ROW WITH ROLLBACK TO
# SAVEPOINT IN ERROR HANDLER
#
# Problem:
# ========
# "SAVEPOINT", "ROLLBACK TO savepoint" wipe out table map on slave during
# execution binary log events. For trigger the map is written to binary log once
# for all trigger body and if trigger contains "SAVEPOINT" or
# "ROLLBACK TO savepoint" statements any trigger's events after these
# statements will not have table map. This results in an assert on slave.
#
# Test:
# =====
# Test case 1:
# Create a trigger with exception handler which rollsback to a savepoint.
# Test proves that there will not be any assert during execution of rolling
# back to savepoint.
#
# Test case 2:
# Create a trigger which calls a procedure which in turn calls an exception
# handler which rollsback to a savepoint. Prove that it doesn't cause any
# assertion during execution.
#
# Test case 3:
# Create a simple trigger which creates a SAVEPOINT and ROLLSBACK to savepoint
# and doesn't follow with any other DML statement. Prove that it doesn't cause
# any assertion during execution.
#
# Test case 4:
# Create a trigger with SAVEPOINT and follows with a DML without ROLLBACK TO
# savepoint. Ensure that data is replicated properly.
#
# Test case 5:
# Create a trigger with SAVEPOINT and it does nothing. Do few DMLS following
# the trigger ensure that the data is replicated properly
#
# Test case 6:
# Create a stored function which creates a SAVEPOINT and ROLLSBACK to
# savepoint. Do few inserts following the stored function call and ensure that
# no assert is generated on slave and all the rows are replicated to slave.
#
# Test case 7:
# Create a stored function which creates a SAVEPOINT alone and follows with
# DMLS without ROLLBACK TO savepoint. Ensure that data is replicated properly.
#
# Test case 8:
# Create a stored function which has SAVEPOINT inside it and does noting. It
# should follow with other DMLs. Ensure that data is replicated properly.
###############################################################################
--source include/not_group_replication_plugin.inc
--source include/have_innodb.inc
--source include/master-slave.inc

--echo #Test case 1:
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY);
CREATE TABLE t3 (f1 INTEGER PRIMARY KEY);
DELIMITER |;

CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW
BEGIN
        DECLARE EXIT HANDLER FOR SQLEXCEPTION
                BEGIN
                        ROLLBACK TO event_logging_1;
                        INSERT t3 VALUES (1);
                END;

        SAVEPOINT event_logging_1;

        INSERT INTO t2 VALUES (1);

        RELEASE SAVEPOINT event_logging_1;

END|
DELIMITER ;|

INSERT INTO t2 VALUES (1);
INSERT INTO t1 VALUES (1);

--source include/show_binlog_events.inc

--sync_slave_with_master

--source include/rpl_connection_master.inc

DROP TRIGGER tr1;
DELETE FROM t1;
DELETE FROM t2;
DELETE FROM t3;

--echo # Test case 2:

DELIMITER |;

CREATE PROCEDURE p1()
BEGIN
        DECLARE EXIT HANDLER FOR SQLEXCEPTION
                BEGIN
                        ROLLBACK TO event_logging_2;
                        INSERT t3 VALUES (3);
                END;

        SAVEPOINT event_logging_2;

        INSERT INTO t2 VALUES (1);

        RELEASE SAVEPOINT event_logging_2;
END|

CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW CALL p1()|

DELIMITER ;|

INSERT INTO t2 VALUES (1);
INSERT INTO t1 VALUES (1);

--source include/show_binlog_events.inc

--sync_slave_with_master

--source include/rpl_connection_master.inc

DROP TABLE t1;
DROP TABLE t2;
DROP TABLE t3;

DROP PROCEDURE p1;

--echo # Test case 3:
--source include/rpl_reset.inc
--source include/rpl_connection_master.inc

CREATE TABLE t (f1 int(10) unsigned NOT NULL, PRIMARY KEY (f1)) ENGINE=InnoDB;

--delimiter |
CREATE TRIGGER t_insert_trig AFTER INSERT ON t
FOR EACH ROW
BEGIN

SAVEPOINT savepoint_1;
ROLLBACK TO savepoint_1;

END |
--delimiter ;

INSERT INTO t VALUES (2);
INSERT INTO t VALUES (3);

--source include/show_binlog_events.inc

SELECT * FROM t;

--source include/sync_slave_sql_with_master.inc

SELECT * FROM t;

--source include/rpl_connection_master.inc
DROP TABLE t;

--echo # Test case 4:
--source include/rpl_reset.inc
--source include/rpl_connection_master.inc
CREATE TABLE t (f1 int(10) unsigned NOT NULL) ENGINE=InnoDB;
CREATE TABLE t1 (f1 int(10) unsigned NOT NULL) ENGINE=InnoDB;

--delimiter |
CREATE TRIGGER t_insert_trig BEFORE INSERT ON t
FOR EACH ROW
BEGIN

SAVEPOINT savepoint_1;
INSERT INTO t1 VALUES (5);
END |
--delimiter ;

INSERT INTO t VALUES (2), (3);
INSERT INTO t1 VALUES (30);
--source include/show_binlog_events.inc

SELECT * FROM t;
SELECT * FROM t1;
--source include/sync_slave_sql_with_master.inc

SELECT * FROM t;
SELECT * FROM t1;

--source include/rpl_connection_master.inc
DROP TABLE t;
DROP TABLE t1;

--echo # Test case 5:
--source include/rpl_reset.inc
--source include/rpl_connection_master.inc
CREATE TABLE t (f1 int(10) unsigned NOT NULL) ENGINE=InnoDB;
CREATE TABLE t1 (f1 int(10) unsigned NOT NULL) ENGINE=InnoDB;

--delimiter |
CREATE TRIGGER t_insert_trig BEFORE INSERT ON t
FOR EACH ROW
BEGIN

SAVEPOINT savepoint_1;
END |

--delimiter ;

INSERT INTO t VALUES (2), (3);
INSERT INTO t1 VALUES (30);
--source include/show_binlog_events.inc

SELECT * FROM t;
SELECT * FROM t1;
--source include/sync_slave_sql_with_master.inc

SELECT * FROM t;
SELECT * FROM t1;

--source include/rpl_connection_master.inc
DROP TABLE t;
DROP TABLE t1;

--echo # Test case 6:
--source include/rpl_reset.inc
--source include/rpl_connection_master.inc
CREATE TABLE t1 (f1 INTEGER ) ENGINE=INNODB;
CREATE TABLE t2 (f1 INTEGER ) ENGINE=INNODB;

--delimiter |

CREATE FUNCTION f1() RETURNS INT
BEGIN
        SAVEPOINT event_logging_2;

        INSERT INTO t1 VALUES (1);

        ROLLBACK TO event_logging_2;
        RETURN 0;
END|

--delimiter ;

BEGIN;
INSERT INTO t2 VALUES (1), (f1()), (2), (4);
COMMIT;
INSERT INTO t2 VALUES (10);
--source include/show_binlog_events.inc

--source include/rpl_connection_master.inc
SELECT * FROM t2;
SELECT * FROM t1;
--source include/sync_slave_sql_with_master.inc
SELECT * FROM t2;
SELECT * FROM t1;

--source include/rpl_connection_master.inc
DROP TABLE t1;
DROP TABLE t2;
DROP FUNCTION f1;

--echo # Test case 7:
--source include/rpl_reset.inc
--source include/rpl_connection_master.inc
CREATE TABLE t1 (f1 INTEGER ) ENGINE=INNODB;
CREATE TABLE t2 (f1 INTEGER ) ENGINE=INNODB;

--delimiter |

CREATE FUNCTION f1() RETURNS INT
BEGIN
        SAVEPOINT event_logging_2;

        INSERT INTO t1 VALUES (1);

        RETURN 0;
END|

--delimiter ;

BEGIN;
INSERT INTO t2 VALUES (1), (f1()), (2), (4);
COMMIT;
INSERT INTO t2 VALUES (10);
--source include/show_binlog_events.inc

--source include/rpl_connection_master.inc
SELECT * FROM t2;
SELECT * FROM t1;
--source include/sync_slave_sql_with_master.inc
SELECT * FROM t2;
SELECT * FROM t1;

--source include/rpl_connection_master.inc
DROP TABLE t1;
DROP TABLE t2;
DROP FUNCTION f1;

--echo # Test case 8:
--source include/rpl_reset.inc
--source include/rpl_connection_master.inc
CREATE TABLE t1 (f1 INTEGER ) ENGINE=INNODB;

--delimiter |

CREATE FUNCTION f1() RETURNS INT
BEGIN
        SAVEPOINT event_logging_2;
        RETURN 0;
END|

--delimiter ;

BEGIN;
INSERT INTO t1 VALUES (1), (f1()), (2), (4);
COMMIT;
INSERT INTO t1 VALUES (10);
--source include/show_binlog_events.inc

--source include/rpl_connection_master.inc
SELECT * FROM t1;
--source include/sync_slave_sql_with_master.inc
SELECT * FROM t1;

--source include/rpl_connection_master.inc
DROP TABLE t1;
DROP FUNCTION f1;

--source include/rpl_end.inc
