# ==== Purpose ====
#
# Check that the logic for re-executing statements using GTID_NEXT
# works as specified.
#
# The following properties are tested when GTID_NEXT is set:
#
#  - SET GTID_NEXT sets @@SESSION.GTID_OWNED.
#
#  - The first statement of a transaction sets @@SESSION.GTID_EXECUTE
#
#  - COMMIT sets @@SESSION.GTID_EXECUTE and clears @@SESSION.GTID_EXECUTE and
#    @@SESSION.GTID_OWNED.
#
#  - ROLLBACK does not change @@SESSION.GTID_EXECUTE, and clears
#    @@SESSION.GTID_EXECUTE and @@SESSION.GTID_OWNED
#
#  - ROLLBACK TO SAVEPOINT never clears @@SESSION.GTID_OWNED
#
#  - ROLLBACK TO SAVEPOINT clears @@SESSION.GTID_EXECUTE if the
#    transaction cache becomes completely empty.
#
#  - When one thread owns a GTID, another session that sets GTID_NEXT
#    to the same GTID will block.
#
#  - When a thread rolls back, a thread waiting for ownership gains
#    ownership.
#
#  - When a thread commits, a thread waiting for ownership skips the
#    transaction.
#
# ==== Implementation ====
#
# We use a table where each row contains a specification of a
# statement, together with a description of how we expect
# @@[GLOBAL|SESSION].GTID_[DONE|OWNED] to change when the statement is
# executed.
#
# In the "main loop", we iterate over the rows in the table.  For each
# row, we execute the statement and check that the @@variables are
# updated as expected.
#
# See comment above "CREATE TABLE stmts" for details.
#
# ==== References ====
#
# Created as part in WL#3584: Global Transaction Identifiers.

--source include/have_innodb.inc
--source include/have_gtid.inc
--source include/not_valgrind.inc
--let $rpl_extra_connections_per_server= 3
--let $rpl_gtid_utils= 1
--source include/master-slave.inc
--source include/have_debug.inc

--echo #### Initialize ####

CREATE table t (a INT PRIMARY KEY) ENGINE = InnoDB;
INSERT INTO t VALUES (1);

--echo #### Specify test cases ####

# This table contains specifications of all tests we are going to
# perform.  It contains the connection to execute in, the statement to
# execute, and the expected outcome in terms of
# @@[GLOBAL|SESSION].GTID_[DONE|OWNED].
#
# Columns:
#  id
#    autoinc PK. This is used only to make it easier to map lines in
#    the result file to what is being tested.
#
#  connection
#    A number identifying the connection to use.
#
#  stmt_type
#    Code specifying what type of statement to execute. Can be one of the
#    following:
#      <SIDNO>:<GNO>
#        Execute the statement SET GTID_NEXT="SID:GNO".
#        We don't want to write out full UUIDs in the specification,
#        because they are too long and unreadable.  Instead, we use
#        two-digit integers as abbreviations. For instance, 37:1 is an
#        abbreviation for 37373737-3737-3737-3737-373737373737:1
#        (cf. the functions NUMBER_TO_UUID and UUID_TO_NUMBER defined
#        in include/gtid_utils.inc)
#      CREATE, INSERT, BEGIN, COMMIT, ROLLBACK
#        Execute the given statement.
#      CREATE-NODROP
#        Like CREATE, this executes a CREATE TABLE, but unlike CREATE,
#        the statement is expected to be skipped, so we do not have to
#        match the statement by a DROP TABLE at the cleanup stage.
#      SAVEPOINT <N>
#        Execute SAVEPOINT SP_<N>
#      ROLLBACK <N>
#        Execute ROLLBACK TO SAVEPOINT SP_<N>
#      send X
#        Asynchronously send statement X (X is one of the
#        specifications above); do not wait for the result.
#      reap
#        Reap (wait for the result of) last query sent on the
#        connection.
#      running
#        Do nothing; just assert that the last query sent by 'send' is
#        still running.
#
#  global_gtid_executed
#    Specifies how @@GLOBAL.GTID_EXECUTE is expected to change after the
#    statement.  This has the form of a gtid_set containing the gtids
#    that were added by the statement.  If the gtid_set begins with
#    '~', the gtids are expected to be removed instead.  UUIDs are
#    abbreviated as in stmt_type (see above).
#
#  session_gtid_executed, gtid_owned
#    Specify how @@SESSION.GTID_EXECUTE and @@[SESSION|GLOBAL].GTID_OWNED
#    are expected to change after the statement.  These have the same
#    form as global_gtid_executed (see above).
#
#  error
#    Expected errno for the statement, or 0 if the statement is
#    expected to succeed.
CREATE TABLE stmts (
  id INT PRIMARY KEY NOT NULL,
  connection INT NOT NULL,
  stmt_type TEXT(100) NOT NULL,
  global_gtid_executed TEXT(10000) NOT NULL,
  session_gtid_executed TEXT(10000) NOT NULL,
  session_gtid_owned TEXT(10000) NOT NULL,
  global_gtid_owned TEXT(10000) NOT NULL,
  error INT NOT NULL)
  ENGINE = InnoDB;

eval INSERT INTO stmts VALUES
#  ID  CON  STATEMENT_TYPE      G.DONE   S.DONE   S.OWNED  G.OWNED  ERROR
  # DML statements
  (1000, 1, '1:1',              '',      '',      '1:1',   '1:1',   0)
 ,(1001, 1, 'AUTOCOMMIT=1',     '',      '',      '',      '',      0)
 ,(1002, 1, 'INSERT',           '1:1',   '',      '~1:1',  '~1:1',  0)
 ,(1003, 1, '1:3',              '',      '',      '1:3',   '1:3',   0)
 ,(1004, 1, 'INSERT',           '1:3',   '',      '~1:3',  '~1:3',  0)
  # skipped DML statements
 ,(1010, 1, '1:3',              '',      '',      '',      '',      0)
 ,(1011, 1, 'INSERT',           '',      '',      '',      '',      0)
 ,(1012, 1, '1:1',              '',      '',      '',      '',      0)
 ,(1013, 1, 'INSERT',           '',      '',      '',      '',      0)
  # DDL statements
 ,(1020, 1, '2:3',              '',      '',      '2:3',   '2:3',   0)
 ,(1021, 1, 'CREATE',           '2:3',   '',      '~2:3',  '~2:3',  0)
 ,(1022, 1, '2:4',              '',      '',      '2:4',   '2:4',   0)
 ,(1023, 1, 'CREATE',           '2:4',   '',      '~2:4',  '~2:4',  0)
  # skipped DDL statements
 ,(1030, 1, '2:3',              '',      '',      '',      '',      0)
 ,(1031, 1, 'CREATE-NODROP',    '',      '',      '',      '',      0)
 ,(1032, 1, '2:4',              '',      '',      '',      '',      0)
 ,(1033, 1, 'CREATE-NODROP',    '',      '',      '',      '',      0)
  # simple transaction
 ,(1040, 1, '4:1',              '',      '',      '4:1',   '4:1',   0)
 ,(1041, 1, 'BEGIN',            '',      '',      '',      '',      0)
 ,(1042, 1,   'INSERT',         '',      '4:1',   '',      '',      0)
 ,(1043, 1,   'INSERT',         '',      '',      '',      '',      0)
 ,(1044, 1, 'COMMIT',           '4:1',   '~4:1',  '~4:1',  '~4:1',  0)
  # skipped simple transaction
 ,(1050, 1, '4:1',              '',      '',      '',      '',      0)
 ,(1051, 1, 'BEGIN',            '',      '',      '',      '',      0)
 ,(1052, 1,   'INSERT',         '',      '',      '',      '',      0)
 ,(1053, 1,   'INSERT',         '',      '',      '',      '',      0)
 ,(1054, 1, 'COMMIT',           '',      '',      '',      '',      0)
  # rollback transaction
 ,(1060, 1, '6:1',              '',      '',      '6:1',   '6:1',   0)
 ,(1061, 1, 'BEGIN',            '',      '',      '',      '',      0)
 ,(1062, 1,   'INSERT',         '',      '6:1',   '',      '',      0)
 ,(1063, 1,   'INSERT',         '',      '',      '',      '',      0)
 ,(1064, 1, 'ROLLBACK',         '',      '~6:1',  '~6:1',  '~6:1',  0)
  # rollback to savepoint, then rollback
 ,(1070, 1, '6:1',              '',      '',      '6:1',   '6:1',   0)
 ,(1071, 1, 'BEGIN',            '',      '',      '',      '',      0)
 ,(1072, 1,   'SAVEPOINT 1',    '',      '',      '',      '',      0)
 ,(1073, 1,     'SAVEPOINT 2',  '',      '',      '',      '',      0)
 ,(1074, 1,       'INSERT',     '',      '6:1',   '',      '',      0)
 ,(1075, 1,       'INSERT',     '',      '',      '',      '',      0)
 ,(1076, 1,     'ROLLBACK 2',   '',      '~6:1',  '',      '',      0)
 ,(1077, 1,     'SAVEPOINT 3',  '',      '',      '',      '',      0)
 ,(1078, 1,       'INSERT',     '',      '6:1',   '',      '',      0)
 ,(1079, 1,       'SAVEPOINT 4','',      '',      '',      '',      0)
 ,(1080, 1,     'ROLLBACK 3',   '',      '~6:1',  '',      '',      0)
 ,(1081, 1,     'INSERT',       '',      '6:1',   '',      '',      0)
 ,(1082, 1,     'SAVEPOINT 2',  '',      '',      '',      '',      0)
 ,(1083, 1,     'ROLLBACK 2',   '',      '',      '',      '',      0)
 ,(1084, 1,   'ROLLBACK 1',     '',      '~6:1',  '',      '',      0)
 ,(1085, 1, 'ROLLBACK',         '',      '',      '~6:1',  '~6:1',  0)
  # empty group
 ,(1090, 1, '9:1',              '',      '',      '9:1',   '9:1',   0)
 ,(1091, 1, 'COMMIT',           '9:1',   '',      '~9:1',  '~9:1',  0)
  # skipped empty group
 ,(1100, 1, '9:1',              '',      '',      '',      '',      0)
 ,(1101, 1, 'COMMIT',           '',      '',      '',      '',      0)
  # rollback 'empty' group
 ,(1110, 1, '11:1',             '',      '',      '11:1',  '11:1',  0)
 ,(1111, 1, 'ROLLBACK',         '',      '',      '~11:1', '~11:1', 0)
  # concurrent group: committed and skipped
 ,(1120, 1, '12:1',             '',      '',      '12:1',  '12:1',  0)
 ,(1121, 2, 'send 12:1',        '',      '',      '',      '',      0)
 ,(1122, 1, 'BEGIN',            '',      '',      '',      '',      0)
 ,(1123, 1, 'INSERT',           '',      '12:1',  '',      '',      0)
 ,(1124, 2, 'running',          '',      '',      '',      '',      0)
 ,(1125, 1, 'COMMIT',           '12:1',  '~12:1', '~12:1', '~12:1', 0)
 ,(1126, 2, 'reap',             '12:1',  '',      '',      '~12:1', 0)
  # concurrent group: rolled back, other thread takes over
 ,(1130, 1, '13:1',             '',      '',      '13:1',  '13:1',  0)
 ,(1131, 2, 'send 13:1',        '',      '',      '',      '',      0)
 ,(1132, 1, 'BEGIN',            '',      '',      '',      '',      0)
 ,(1133, 1, 'INSERT',           '',      '13:1',  '',      '',      0)
 ,(1134, 2, 'running',          '',      '',      '',      '',      0)
 ,(1135, 1, 'ROLLBACK',         '',      '~13:1', '~13:1', '',      0)
 ,(1136, 2, 'reap',             '',      '',      '13:1',  '',      0)
 ,(1137, 2, 'BEGIN',            '',      '',      '',      '',      0)
 ,(1138, 2, 'INSERT',           '',      '13:1',  '',      '',      0)
 ,(1139, 2, 'COMMIT',           '13:1',  '~13:1', '~13:1', '~13:1', 0)
  # concurrent group: rolled back, ownership transferred from 1->2->3->1
 ,(1140, 1, '14:1',             '',      '',      '14:1',  '14:1',  0)
 ,(1141, 2, 'send 14:1',        '',      '',      '',      '',      0)
 ,(1142, 1, 'BEGIN',            '',      '',      '',      '',      0)
 ,(1143, 1,   'INSERT',         '',      '14:1',  '',      '',      0)
 ,(1144, 2, 'running',          '',      '',      '',      '',      0)
 ,(1145, 1, 'ROLLBACK',         '',      '~14:1', '~14:1', '',      0)
 ,(1146, 2, 'reap',             '',      '',      '14:1',  '',      0)
 ,(1147, 2, 'BEGIN',            '',      '',      '',      '',      0)
 ,(1148, 2,   'INSERT',         '',      '14:1',  '',      '',      0)
 ,(1149, 3, 'send 14:1',        '',      '',      '',      '',      0)
 ,(1150, 3, 'running',          '',      '',      '',      '',      0)
 ,(1151, 2, 'ROLLBACK',         '',      '~14:1', '~14:1', '',      0)
 ,(1152, 3, 'reap',             '',      '',      '14:1',  '',      0)
 ,(1153, 1, 'send 14:1',        '',      '',      '',      '',      0)
 ,(1154, 3, 'BEGIN',            '',      '',      '',      '',      0)
 ,(1155, 3,   'INSERT',         '',      '14:1',  '',      '',      0)
 ,(1156, 1, 'running',          '',      '',      '',      '',      0)
 ,(1157, 3, 'ROLLBACK',         '',      '~14:1', '~14:1', '',      0)
 ,(1158, 1, 'reap',             '',      '',      '14:1',  '',      0)
 ,(1159, 1, 'BEGIN',            '',      '',      '',      '',      0)
 ,(1160, 1,   'INSERT',         '',      '14:1',  '',      '',      0)
 ,(1161, 1, 'COMMIT',           '14:1',  '~14:1', '~14:1', '~14:1', 0)
  # concurrent group and rollback to savepoint
 ,(1170, 1, '17:1',             '',      '',      '17:1',  '17:1',  0)
 ,(1171, 2, 'send 17:1',        '',      '',      '',      '',      0)
 ,(1172, 1, 'BEGIN',            '',      '',      '',      '',      0)
 ,(1173, 1,   'SAVEPOINT 1',    '',      '',      '',      '',      0)
 ,(1174, 1,     'INSERT',       '',      '17:1',  '',      '',      0)
 ,(1175, 1,   'ROLLBACK 1',     '',      '~17:1', '',      '',      0)
 ,(1176, 1,   'INSERT',         '',      '17:1',  '',      '',      0)
 ,(1177, 2, 'running',          '',      '',      '',      '',      0)
 ,(1178, 1, 'ROLLBACK',         '',      '~17:1', '~17:1', '',      0)
 ,(1179, 2, 'reap',             '',      '',      '17:1',  '',      0)
 ,(1180, 2, 'BEGIN',            '',      '',      '',      '',      0)
 ,(1181, 2, 'INSERT',           '',      '17:1',  '',      '',      0)
 ,(1182, 2, 'COMMIT',           '17:1',  '~17:1', '~17:1', '~17:1', 0)
  # rollback to savepoint, then commit
 ,(1190, 1, '19:1',             '',      '',      '19:1',  '19:1',  0)
 ,(1191, 1, 'BEGIN',            '',      '',      '',      '',      0)
 ,(1192, 1,   'SAVEPOINT 1',    '',      '',      '',      '',      0)
 ,(1193, 1,     'SAVEPOINT 2',  '',      '',      '',      '',      0)
 ,(1194, 1,       'INSERT',     '',      '19:1',  '',      '',      0)
 ,(1195, 1,       'INSERT',     '',      '',      '',      '',      0)
 ,(1196, 1,     'ROLLBACK 2',   '',      '~19:1', '',      '',      0)
 ,(1197, 1,     'SAVEPOINT 3',  '',      '',      '',      '',      0)
 ,(1198, 1,       'INSERT',     '',      '19:1',  '',      '',      0)
 ,(1199, 1,       'SAVEPOINT 4','',      '',      '',      '',      0)
 ,(1200, 1,     'ROLLBACK 3',   '',      '~19:1', '',      '',      0)
 ,(1201, 1,     'INSERT',       '',      '19:1',  '',      '',      0)
 ,(1202, 1,     'SAVEPOINT 2',  '',      '',      '',      '',      0)
 ,(1203, 1,     'ROLLBACK 2',   '',      '',      '',      '',      0)
 ,(1204, 1,   'ROLLBACK 1',     '',      '~19:1', '',      '',      0)
 ,(1205, 1, 'COMMIT',           '19:1', '',      '~19:1', '~19:1', 0)
#
# The following is waiting for BUG#13687542
#
#  # failing DML in transaction
# ,(1190, 1, '19:1',             '',      '',      '19:1',  '19:1',  0)
# ,(1191, 1, 'INSERT-ERROR',     '',      '',      '',      '',      1062)#dup
# ,(1192, 1, 'ROLLBACK',         '',      '',      '~19:1', '~19:1', 0)
#  # failing DDL in transaction
# ,(1200, 1, '20:1',             '',      '',      '20:1',  '20:1',  0)
# ,(1201, 1, 'CREATE-ERROR',     '',      '',      '',      '',      1062)#dup
# ,(1202, 1, 'ROLLBACK',         '',      '',      '~20:1', '~20:1', 0)
;

# Clear binlog to get better debug info
--source include/rpl_reset.inc

--echo #### Test ####

if (!$rpl_debug)
{
  --disable_query_log
}
--let $id= `SELECT MIN(id) FROM stmts`
--let $max_id= `SELECT MAX(id) FROM stmts`
while ($id <= $max_id)
{
  while (`SELECT COUNT(*) = 0 FROM stmts WHERE id = $id`)
  {
    --inc $id
  }
  --echo ==== row-id = $id ====
  --let $connection= `SELECT connection FROM stmts WHERE id = $id`
  --let $stmt_type= `SELECT stmt_type FROM stmts WHERE id = $id`
  --let $error= `SELECT error FROM stmts WHERE id = $id`
  --let $orig_stmt_type= $stmt_type

  --let $send_reap=
  if (`SELECT '$stmt_type' REGEXP '^send '`)
  {
    --let $stmt_type= `SELECT SUBSTR('$stmt_type', 6)`
    --let $send_reap= send
  }
  --let $stmt=
  if ($stmt_type == 'reap')
  {
    --let $send_reap= reap
  }
  if ($stmt_type == 'running')
  {
    --let $send_reap= running
  }
  if ($stmt_type == 'INSERT')
  {
    --let $stmt= INSERT INTO t VALUES ($id)
  }
  if ($stmt_type == 'INSERT-ERROR')
  {
    --let $stmt= INSERT INTO t VALUES (1)
  }
  if ($stmt_type == 'CREATE')
  {
    --let $stmt= CREATE TABLE t_$id (a INT) ENGINE = InnoDB
    --let $drop_stmt= $drop_stmt DROP TABLE t_$id;
  }
  if ($stmt_type == 'CREATE-ERROR')
  {
    --let $stmt= CREATE TABLE t (a INT) ENGINE = InnoDB;
  }
  if ($stmt_type == 'CREATE-NODROP')
  {
    --let $stmt= CREATE TABLE t_$id (a INT) ENGINE = InnoDB
  }
  if ($stmt_type == 'BEGIN')
  {
    --let $stmt= BEGIN
  }
  if ($stmt_type == 'COMMIT')
  {
    --let $stmt= COMMIT
  }
  if ($stmt_type == 'ROLLBACK')
  {
    --let $stmt= ROLLBACK
  }
  if ($stmt_type == 'AUTOCOMMIT=0')
  {
    --let $stmt= SET AUTOCOMMIT = 0
  }
  if ($stmt_type == 'AUTOCOMMIT=1')
  {
    --let $stmt= SET AUTOCOMMIT = 1
  }
  if (`SELECT '$stmt_type' REGEXP '^SAVEPOINT [0-9][0-9]*'`)
  {
    --let $stmt= `SELECT CONCAT('SAVEPOINT SP_', SUBSTR('$stmt_type', 11))`
  }
  if (`SELECT '$stmt_type' REGEXP '^ROLLBACK [0-9][0-9]*'`)
  {
    --let $stmt= `SELECT CONCAT('ROLLBACK TO SP_', SUBSTR('$stmt_type', 10))`
  }
  if (`SELECT '$stmt_type' REGEXP '^[0-9][0-9]*:[0-9][0-9]*'`)
  {
    --let $stmt= `SELECT CONCAT('SET GTID_NEXT = "', NUMBER_TO_UUID('$stmt_type'), '"')`
  }
  if ($stmt == '')
  {
    if ($stmt_type != reap)
    {
      if ($stmt_type != running)
      {
        --echo unrecognized statement specification: stmt_type='$stmt_type' orig_stmt_type='$orig_stmt_type' stmt='$stmt'
        --die error in test: unrecognized statement specification
      }
    }
  }

  --let $rpl_connection_name= server_1_$connection
  --source include/rpl_connection.inc

  --let $rpl_connection_silent= 1

  --echo $orig_stmt_type

  if ($send_reap != 'reap')
  {
    if ($send_reap != 'running')
    {
      SET @session_gtid_executed= @@SESSION.GTID_EXECUTED;
      SET @global_gtid_executed= @@GLOBAL.GTID_EXECUTED;
      SET @session_gtid_owned= @@SESSION.GTID_OWNED;
      SET @global_gtid_owned= SUBSTRING_INDEX(@@GLOBAL.GTID_OWNED, '#', 1);

      --let $eval_no_result= 1
      --let $include_silent= 1
      --let $eval_expr= SET @binlog_file_before= "[master:SHOW MASTER STATUS, File, 1]"
      --source include/eval.inc
      --let $eval_expr= SET @binlog_pos_before= [master:SHOW MASTER STATUS, Position, 1]
      --source include/eval.inc
      --let $eval_expr= SET @slave_global_gtid_executed= "[slave:SELECT @@GLOBAL.GTID_EXECUTED]"
      --source include/eval.inc
      --let $include_silent= 0
      --let $eval_no_result= 0
    }
  }

  if ($rpl_debug)
  {
    --echo DEBUG: stmt='$stmt' connection='$connection' send_reap='$send_reap' error='$error'
  }

  # Execute statement (or send/reap)
  if ($send_reap == '')
  {
    if ($error != 0)
    {
      # This does not work because of BUG#13687542
      --error $error
      eval $stmt;
    }
    if ($error == 0)
    {
      eval $stmt;
    }
  }
  if ($send_reap == 'send')
  {
    --let $last_send_id= `SELECT CONNECTION_ID()`
    --let $last_send_stmt= $stmt
    --send
    eval $stmt;
    --connection master
    --let $wait_condition= SELECT Info = '$last_send_stmt' FROM INFORMATION_SCHEMA.PROCESSLIST WHERE Id = $last_send_id
    --source include/wait_condition.inc
  }
  if ($send_reap == 'reap')
  {
    if ($error != 0)
    {
      --error $error
      reap;
    }
    if ($error == 0)
    {
      reap;
    }
  }

  --let $rpl_connection_name= master
  --source include/rpl_connection.inc

  # Check that thread is still running query
  if ($send_reap == 'running')
  {
    # Don't use include/assert.inc because $last_send_stmt may contain quotes
    --echo Checking that thread is still running query
    --let $info= `SELECT Info FROM INFORMATION_SCHEMA.PROCESSLIST WHERE Id = $last_send_id`
    if ($info != $last_send_stmt)
    {
      --source include/show_rpl_debug_info.inc
      --echo info='$info'
      --echo last_send_stmt='$last_send_stmt'
      --die Error: thread was supposed to be still running query
    }
  }

  # Check that variables have their expected values.
  if ($send_reap != 'send')
  {
    if ($send_reap != 'running')
    {
      --source include/sync_slave_sql_with_master.inc
      --connection master
      # Concurrent tests require two or more connections and at least one connection sends  
      # the statements in async mode (via send/reap command). We need to make sure that
      # SET GTID_NEXT is completed for all connections before getting values of 
      # GTID variables and if COMMIT/ROLLBACK executed for any connection.
      if (`SELECT '$stmt' REGEXP '^(COMMIT|ROLLBACK)\$'`)
      {
        --let $wait_condition= SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State LIKE 'waiting for GTID %'
        --source include/wait_condition.inc
      }
                                              
      --let $text_0= @@GLOBAL.GTID_EXECUTED
      --let $after_0= [server_1_$connection:SELECT @@GLOBAL.GTID_EXECUTED]
      --let $before_0= @global_gtid_executed
      --let $col_0= global_gtid_executed

      --let $text_1= @@SESSION.GTID_EXECUTED
      --let $after_1= [server_1_$connection:SELECT @@SESSION.GTID_EXECUTED]
      --let $before_1= @session_gtid_executed
      --let $col_1= session_gtid_executed

      --let $text_2= @@SESSION.GTID_OWNED
      --let $after_2= [server_1_$connection:SELECT @@SESSION.GTID_OWNED]
      --let $before_2= @session_gtid_owned
      --let $col_2= session_gtid_owned

      --let $text_3= @@GLOBAL.GTID_OWNED
      --let $after_3= [server_1_$connection:SELECT SUBSTRING_INDEX(@@GLOBAL.GTID_OWNED, "#", 1)]
      --let $before_3= @global_gtid_owned
      --let $col_3= global_gtid_owned

      --let $text_4= slave:@@GLOBAL.GTID_EXECUTED
      --let $after_4= [slave: SELECT @@GLOBAL.GTID_EXECUTED]
      --let $before_4= @slave_global_gtid_executed
      --let $col_4= global_gtid_executed

      --let $i= 0
      while ($i < 5)
      {
        --let $text= \$text_$i
        --let $after= \$after_$i
        --let $before= \$before_$i
        --let $col= \$col_$i

        # $after = the value of the $variable now
        --let $eval_expr= "$after"
        --let $include_silent= 1
        --source include/eval.inc
        --let $include_silent= 0
        --let $after= $eval_result

        # $before = the value of the $variable before the statement
        --let $rpl_connection_name= server_1_$connection
        --source include/rpl_connection.inc
        --let $before= `SELECT $before`
        --let $rpl_connection_name= master
        --source include/rpl_connection.inc

        # $diff = the expected change in the variable
        --let $diff= `SELECT NUMBER_TO_UUID($col) FROM stmts WHERE id = $id`

        if ($rpl_debug)
        {
          --echo i='$i' before='$before' diff='$diff' after='$after'
        }

        # Assert that before + diff = after
        let $assert_text= `
          SELECT CONCAT("#$id $text: '",
                        UUID_TO_NUMBER('$before'), "' + '",
                        UUID_TO_NUMBER('$diff'), "' = '",
                        UUID_TO_NUMBER('$after'), "'")`;
        --let $assert_cond= GTID_COMPARE("$before", "$diff", "$after")
        --source include/assert.inc

        --inc $i
      }

      # Assert that binlog changed or didn't change (according to
      # whether gtid_executed changed/didn't change).

      --let $rpl_connection_name= master
      --source include/rpl_connection.inc

      --let $changed_binlog= `SELECT global_gtid_executed != '' FROM stmts WHERE id = $id`
      if ($changed_binlog)
      {
        let $assert_cond=
          [SHOW MASTER STATUS, Position, 1] >
          [server_1_$connection:SELECT @binlog_pos_before];
        --let $assert_text= Something was written to the binlog
        --source include/assert.inc

        let $assert_cond=
          "[SHOW BINLOG EVENTS IN
            "[server_1_$connection:SELECT @binlog_file_before]"
            FROM [server_1_$connection:SELECT @binlog_pos_before]
            LIMIT 1, Event_type, 1]" = "Gtid";
        --let $assert_text= The first added event in the binlog should be a Gtid_log_event
        --source include/assert.inc
        #--let $assert_cond= "[SHOW BINLOG EVENTS IN "$binlog_file_before" FROM $binlog_pos_before LIMIT 1, Info, 1]" = "SET GTID_NEXT = "
      }
      if (!$changed_binlog)
      {
        let $assert_cond=
          "[SHOW MASTER STATUS, File, 1]" =
          "[server_1_$connection:SELECT @binlog_file_before]";
        --let $assert_text= Binlog was not rotated
        --source include/assert.inc

        let $assert_cond=
          [SHOW MASTER STATUS, Position, 1] =
          [server_1_$connection:SELECT @binlog_pos_before];
        --let $assert_text= Binlog position was not updated
        --source include/assert.inc
      }
    }
  }
  --let $rpl_connection_silent= 0

  --inc $id
}

--enable_query_log

# The following partially tests what should be tested above, in the
# test cases commented-out waiting for BUG#13687542 to be fixed.  When
# the bug has been fixed, please uncomment the code above and remove
# this.

if (!$fixed_bug13687542)
{
  SET GTID_NEXT = 'AUTOMATIC';
  CREATE TABLE t1 (a INT);
  eval SET GTID_NEXT = '$uuida:1';
  --error ER_TABLE_EXISTS_ERROR
  CREATE TABLE t1 (a INT);

  SET GTID_NEXT = 'AUTOMATIC';
  eval SET GTID_NEXT = '$uuida:1';
  --error ER_DUP_ENTRY
  INSERT INTO t VALUES (1);

  SET GTID_NEXT = 'AUTOMATIC';
  DROP TABLE t1;
}

--echo #### Clean up ####

--eval $drop_stmt
DROP TABLE stmts;
DROP TABLE t;

--source include/rpl_end.inc
