#
# BUG#42749: infinite loop writing to row based binlog - processlist shows
# "freeing items"
#
#
# WHY
# ===
#
#   This bug would make table map event to report data_written one
#   byte less than what would actually be written in its body. This
#   would cause one byte shorter event end_log_pos. The ultimate
#   impact was that it would make fixing the position in
#   MYSQL_BIN_LOG::write_cache bogus or end up in an infinite loop.
#
# HOW
# ===
#
#   Checking that the patch fixes the problem is done as follows:
#
#     i) one table with m_field_metadata sized at 290
#    ii) an insert is performed;
#   iii) the logs are flushed;
#    iv) mysqlbinlog is used to check if it succeeds.
# 
#   In step iv), before the bug was fixed, the test case would fail
#   with mysqlbinlog reporting that it was unable to succeed in
#   reading the event.

-- source include/master-slave.inc
-- source include/have_innodb.inc
-- source include/have_binlog_format_row.inc

-- disable_warnings
DROP TABLE IF EXISTS `t1`;
-- enable_warnings

-- echo ### TABLE with field_metadata_size == 290
CREATE TABLE `t1` (
  `c1` int(11) NOT NULL AUTO_INCREMENT,
  `c2` varchar(30) NOT NULL,
  `c3` varchar(30) DEFAULT NULL,
  `c4` varchar(30) DEFAULT NULL,
  `c5` varchar(30) DEFAULT NULL,
  `c6` varchar(30) DEFAULT NULL,
  `c7` varchar(30) DEFAULT NULL,
  `c8` varchar(30) DEFAULT NULL,
  `c9` varchar(30) DEFAULT NULL,
  `c10` varchar(30) DEFAULT NULL,
  `c11` varchar(30) DEFAULT NULL,
  `c12` varchar(30) DEFAULT NULL,
  `c13` varchar(30) DEFAULT NULL,
  `c14` varchar(30) DEFAULT NULL,
  `c15` varchar(30) DEFAULT NULL,
  `c16` varchar(30) DEFAULT NULL,
  `c17` varchar(30) DEFAULT NULL,
  `c18` varchar(30) DEFAULT NULL,
  `c19` varchar(30) DEFAULT NULL,
  `c20` varchar(30) DEFAULT NULL,
  `c21` varchar(30) DEFAULT NULL,
  `c22` varchar(30) DEFAULT NULL,
  `c23` varchar(30) DEFAULT NULL,
  `c24` varchar(30) DEFAULT NULL,
  `c25` varchar(30) DEFAULT NULL,
  `c26` varchar(30) DEFAULT NULL,
  `c27` varchar(30) DEFAULT NULL,
  `c28` varchar(30) DEFAULT NULL,
  `c29` varchar(30) DEFAULT NULL,
  `c30` varchar(30) DEFAULT NULL,
  `c31` varchar(30) DEFAULT NULL,
  `c32` varchar(30) DEFAULT NULL,
  `c33` varchar(30) DEFAULT NULL,
  `c34` varchar(30) DEFAULT NULL,
  `c35` varchar(30) DEFAULT NULL,
  `c36` varchar(30) DEFAULT NULL,
  `c37` varchar(30) DEFAULT NULL,
  `c38` varchar(30) DEFAULT NULL,
  `c39` varchar(30) DEFAULT NULL,
  `c40` varchar(30) DEFAULT NULL,
  `c41` varchar(30) DEFAULT NULL,
  `c42` varchar(30) DEFAULT NULL,
  `c43` varchar(30) DEFAULT NULL,
  `c44` varchar(30) DEFAULT NULL,
  `c45` varchar(30) DEFAULT NULL,
  `c46` varchar(30) DEFAULT NULL,
  `c47` varchar(30) DEFAULT NULL,
  `c48` varchar(30) DEFAULT NULL,
  `c49` varchar(30) DEFAULT NULL,
  `c50` varchar(30) DEFAULT NULL,
  `c51` varchar(30) DEFAULT NULL,
  `c52` varchar(30) DEFAULT NULL,
  `c53` varchar(30) DEFAULT NULL,
  `c54` varchar(30) DEFAULT NULL,
  `c55` varchar(30) DEFAULT NULL,
  `c56` varchar(30) DEFAULT NULL,
  `c57` varchar(30) DEFAULT NULL,
  `c58` varchar(30) DEFAULT NULL,
  `c59` varchar(30) DEFAULT NULL,
  `c60` varchar(30) DEFAULT NULL,
  `c61` varchar(30) DEFAULT NULL,
  `c62` varchar(30) DEFAULT NULL,
  `c63` varchar(30) DEFAULT NULL,
  `c64` varchar(30) DEFAULT NULL,
  `c65` varchar(30) DEFAULT NULL,
  `c66` varchar(30) DEFAULT NULL,
  `c67` varchar(30) DEFAULT NULL,
  `c68` varchar(30) DEFAULT NULL,
  `c69` varchar(30) DEFAULT NULL,
  `c70` varchar(30) DEFAULT NULL,
  `c71` varchar(30) DEFAULT NULL,
  `c72` varchar(30) DEFAULT NULL,
  `c73` varchar(30) DEFAULT NULL,
  `c74` varchar(30) DEFAULT NULL,
  `c75` varchar(30) DEFAULT NULL,
  `c76` varchar(30) DEFAULT NULL,
  `c77` varchar(30) DEFAULT NULL,
  `c78` varchar(30) DEFAULT NULL,
  `c79` varchar(30) DEFAULT NULL,
  `c80` varchar(30) DEFAULT NULL,
  `c81` varchar(30) DEFAULT NULL,
  `c82` varchar(30) DEFAULT NULL,
  `c83` varchar(30) DEFAULT NULL,
  `c84` varchar(30) DEFAULT NULL,
  `c85` varchar(30) DEFAULT NULL,
  `c86` varchar(30) DEFAULT NULL,
  `c87` varchar(30) DEFAULT NULL,
  `c88` varchar(30) DEFAULT NULL,
  `c89` varchar(30) DEFAULT NULL,
  `c90` varchar(30) DEFAULT NULL,
  `c91` varchar(30) DEFAULT NULL,
  `c92` varchar(30) DEFAULT NULL,
  `c93` varchar(30) DEFAULT NULL,
  `c94` varchar(30) DEFAULT NULL,
  `c95` varchar(30) DEFAULT NULL,
  `c96` varchar(30) DEFAULT NULL,
  `c97` varchar(30) DEFAULT NULL,
  `c98` varchar(30) DEFAULT NULL,
  `c99` varchar(30) DEFAULT NULL,
  `c100` varchar(30) DEFAULT NULL,
  `c101` varchar(30) DEFAULT NULL,
  `c102` varchar(30) DEFAULT NULL,
  `c103` varchar(30) DEFAULT NULL,
  `c104` varchar(30) DEFAULT NULL,
  `c105` varchar(30) DEFAULT NULL,
  `c106` varchar(30) DEFAULT NULL,
  `c107` varchar(30) DEFAULT NULL,
  `c108` varchar(30) DEFAULT NULL,
  `c109` varchar(30) DEFAULT NULL,
  `c110` varchar(30) DEFAULT NULL,
  `c111` varchar(30) DEFAULT NULL,
  `c112` varchar(30) DEFAULT NULL,
  `c113` varchar(30) DEFAULT NULL,
  `c114` varchar(30) DEFAULT NULL,
  `c115` varchar(30) DEFAULT NULL,
  `c116` varchar(30) DEFAULT NULL,
  `c117` varchar(30) DEFAULT NULL,
  `c118` varchar(30) DEFAULT NULL,
  `c119` varchar(30) DEFAULT NULL,
  `c120` varchar(30) DEFAULT NULL,
  `c121` varchar(30) DEFAULT NULL,
  `c122` varchar(30) DEFAULT NULL,
  `c123` varchar(30) DEFAULT NULL,
  `c124` varchar(30) DEFAULT NULL,
  `c125` varchar(30) DEFAULT NULL,
  `c126` varchar(30) DEFAULT NULL,
  `c127` varchar(30) DEFAULT NULL,
  `c128` varchar(30) DEFAULT NULL,
  `c129` varchar(30) DEFAULT NULL,
  `c130` varchar(30) DEFAULT NULL,
  `c131` varchar(30) DEFAULT NULL,
  `c132` varchar(30) DEFAULT NULL,
  `c133` varchar(30) DEFAULT NULL,
  `c134` varchar(30) DEFAULT NULL,
  `c135` varchar(30) DEFAULT NULL,
  `c136` varchar(30) DEFAULT NULL,
  `c137` varchar(30) DEFAULT NULL,
  `c138` varchar(30) DEFAULT NULL,
  `c139` varchar(30) DEFAULT NULL,
  `c140` varchar(30) DEFAULT NULL,
  `c141` varchar(30) DEFAULT NULL,
  `c142` varchar(30) DEFAULT NULL,
  `c143` varchar(30) DEFAULT NULL,
  `c144` varchar(30) DEFAULT NULL,
  `c145` varchar(30) DEFAULT NULL,
  `c146` varchar(30) DEFAULT NULL,
  PRIMARY KEY (`c1`)
) ENGINE=InnoDB;

LOCK TABLES `t1` WRITE;
INSERT INTO `t1`(c2) VALUES ('1');
FLUSH LOGS;

-- sync_slave_with_master
-- connection master

-- echo ### assertion: the slave replicated event successfully and tables match
-- let $diff_table_1=master:test.t1
-- let $diff_table_2=slave:test.t1
-- source include/diff_tables.inc

DROP TABLE `t1`;

-- connection master
-- sync_slave_with_master
-- connection master

-- echo === Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail.

-- let $MYSQLD_DATADIR= `SELECT @@datadir`
-- exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog
-- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog

#############################################################
# BUG#50018: binlog corruption when table has many columns
#
# Same test from BUG#42749, but now we generate some SQL which
# creates and inserts into tables with metadata size from 249
# to 258.
# 
# The test works as follows:
#  1. SQL for several CREATE TABLE and INSERTS are generated 
#     into a file.
#  2. This file is then "sourced"
#  3. The slave is synchronized with the master
#  4. FLUSH LOGS on master
#  5. Compare tables on master and slave.
#  6. run mysqlbinlog on  master's binary log
#
# Steps #5 and #6 assert that binary log is not corrupted 
# in both cases: when slave is replaying events and when
# mysqlbinlog is used to read the binary log

-- source include/master-slave-reset.inc
-- connection master

# Create several tables with field_metadata_size ranging
# from 249 to 258 (so that we cover 251 and 255 range).
# This should exercise the switch between using 1 or 3
# bytes to pack m_field_metadata_size.
# 
# Each varchar field takes up to 2 metadata bytes, see:
#
#  Field_varstring::do_save_field_metadata (field.cc)
#
# The float field takes 1 byte, see:
#
#  Field_float::do_save_field_metadata (field.cc)
#

-- let $generated_sql= $MYSQLTEST_VARDIR/tmp/b50018.sql
-- let B50018_FILE= $generated_sql

-- echo ### action: generating several tables with different metadata 
-- echo ###         sizes (resorting to perl)
-- perl
my $file= $ENV{'B50018_FILE'};
open(FILE, ">", "$file") or die "Unable to open bug 50018 generated SQL file: $!" ;

my $tables= "";
my $ntables= 10;
my $base_ncols= 124;

for my $i (1..$ntables)
{
  my $ncols= $base_ncols + $i;
  my $metadata_size= $ncols_variable * 2 + 1; 

  print FILE "-- echo ### testing table with " . ($base_ncols*2 + $i) . " field metadata size.\n";
  print FILE "CREATE TABLE t$i (\n";
  for my $n (1..$base_ncols)
  {
    print FILE "c$n VARCHAR(30) NOT NULL DEFAULT 'BUG#50018',\n";
  }

  for my $n (1..$i)
  {
    print FILE "c" . ($base_ncols+$n) . " FLOAT NOT NULL DEFAULT 0";
    if ($n < $i)
    {
      print FILE ",\n";
    }
  }

  print FILE ") Engine=InnoDB;\n";

  $tables.= " t$i WRITE";
  if ($i < $ntables)
  {
    $tables .=",";
  }
    
  print FILE "LOCK TABLES t$i WRITE;\n";
  print FILE "INSERT INTO t$i(c". ($base_ncols+1) . ") VALUES (50018);\n";
  print FILE "UNLOCK TABLES;";
}

close(FILE);

EOF

## we don't need this in the result file
## however, for debugging purposes you 
## may want to reactivate query logging
-- disable_query_log 
-- source $generated_sql
-- enable_query_log

-- sync_slave_with_master
-- connection master

FLUSH LOGS;

-- let $ntables=10
while($ntables)
{
  -- echo ### assertion: the slave replicated event successfully and tables match for t$ntables
  -- let $diff_table_1=master:test.t$ntables
  -- let $diff_table_2=slave:test.t$ntables
  -- source include/diff_tables.inc

  -- connection master
  -- disable_query_log
  -- eval DROP TABLE t$ntables
  -- enable_query_log
  -- sync_slave_with_master
  -- connection master

  -- dec $ntables
}

-- echo ### assertion: check that binlog is not corrupt. Using mysqlbinlog to 
-- echo ###            detect failure. Before the patch mysqlbinlog would find 
-- echo ###            a corrupted event, thence would fail.
-- let $MYSQLD_DATADIR= `SELECT @@datadir`
-- exec $MYSQL_BINLOG -v --hex $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog

## clean up
## For debugging purposes you might want not to remove these
-- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog
-- remove_file $generated_sql
-- source include/master-slave-end.inc
