summaryrefslogtreecommitdiff
path: root/mysql-test/extra
diff options
context:
space:
mode:
authorMats Kindahl <mats@mysql.com>2008-06-30 22:11:18 +0200
committerMats Kindahl <mats@mysql.com>2008-06-30 22:11:18 +0200
commit711305e2c5772d3fd1f555a27ebd5bcb94fd6a77 (patch)
tree99d0103a1bedf9e6a2c68aa7ca343d20d8dafc6d /mysql-test/extra
parent8a2f17d19c731934d954b57f01ba3f2f330012ed (diff)
downloadmariadb-git-711305e2c5772d3fd1f555a27ebd5bcb94fd6a77.tar.gz
BUG#37426: RBR breaks for CHAR() UTF-8 fields > 85 chars
In order to handle CHAR() fields, 8 bits were reserved for the size of the CHAR field. However, instead of denoting the number of characters in the field, field_length was used which denotes the number of bytes in the field. Since UTF-8 fields can have three bytes per character (and has been extended to have four bytes per character in 6.0), an extra two bits have been encoded in the field metadata work for fields of type Field_string (i.e., CHAR fields). Since the metadata word is filled, the extra bits have been encoded in the upper 4 bits of the real type (the most significant byte of the metadata word) by computing the bitwise xor of the extra two bits. Since the upper 4 bits of the real type always is 1111 for Field_string, this means that for fields of length <256, the encoding is identical to the encoding used in pre-5.1.26 servers, but for lengths of 256 or more, an unrecognized type is formed, causing an old slave (that does not handle lengths of 256 or more) to stop. mysql-test/extra/rpl_tests/rpl_row_basic.test: Adding test cases for replicating UTF-8 fields of lengths of 256 or more (bytes). mysql-test/suite/binlog/r/binlog_base64_flag.result: Result file change. mysql-test/suite/binlog/t/binlog_base64_flag.test: Adding tests to trigger check that an error is generated when replicating from a 5.1.25 server for tables with a CHAR(128) but not when replicating a table with a CHAR(63). Although the bug indicates that the limit is 83, we elected to use CHAR(63) since 6.0 uses 4-byte UTF-8, and anything exceeding 63 would then cause the test to fail when the patch is merged to 6.0. mysql-test/suite/bugs/combinations: Adding combinations file to run all bug reports in all binlog modes (where applicable). mysql-test/suite/bugs/r/rpl_bug37426.result: Result file change. mysql-test/suite/bugs/t/rpl_bug37426.test: Added test for reported bug. mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result: Result file change. mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result: Result file change. sql/field.cc: Encoding an extra two bits in the most significant nibble (4 bits) of the metadata word. Adding assertions to ensure that no attempt is made to use lengths longer than supported. Extending compatible_field_size() function with an extra parameter holding a Relay_log_instace for error reporting. Field_string::compatible_field_size() now reports an error if field size for a CHAR is >255. sql/field.h: Field length is now computed from most significant 4 bits of metadata word, or is equal to the row pack length if there is no metadata. Extending compatible_field_size() function with an extra parameter holding a Relay_log_instace for error reporting. sql/rpl_utility.cc: Adding relay log parameter to compatible_field_size(). Minor refactoring to eliminate duplicate code. sql/slave.cc: Extending rpl_master_has_bug() with a single-argument predicate function and a parameter to the predicate function. The predicate function can be used to test for extra conditions for the bug before writing an error message. sql/slave.h: Extending rpl_master_has_bug() with a single-argument predicate function and a parameter to the predicate function. The predicate function can be used to test for extra conditions for the bug before writing an error message. Also removing gratuitous default argument. sql/sql_insert.cc: Changing calls to rpl_master_has_bug() to adapt to changed signature.
Diffstat (limited to 'mysql-test/extra')
-rw-r--r--mysql-test/extra/rpl_tests/rpl_row_basic.test149
1 files changed, 148 insertions, 1 deletions
diff --git a/mysql-test/extra/rpl_tests/rpl_row_basic.test b/mysql-test/extra/rpl_tests/rpl_row_basic.test
index 48ddbaf244a..59f049e2bfa 100644
--- a/mysql-test/extra/rpl_tests/rpl_row_basic.test
+++ b/mysql-test/extra/rpl_tests/rpl_row_basic.test
@@ -259,7 +259,7 @@ DELETE FROM t1;
query_vertical SELECT COUNT(*) FROM t1 ORDER BY c1,c2;
sync_slave_with_master;
set @@global.slave_exec_mode= default;
-let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1);
+let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
disable_query_log;
eval SELECT "$last_error" AS Last_SQL_Error;
enable_query_log;
@@ -272,3 +272,150 @@ query_vertical SELECT COUNT(*) FROM t1 ORDER BY c1,c2;
connection master;
DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8;
sync_slave_with_master;
+
+#
+# BUG#37426: RBR breaks for CHAR() UTF8 fields > 85 chars
+#
+
+# We have 4 combinations to test with respect to the field length
+# (i.e., the number of bytes) of the CHAR fields:
+#
+# 1. Replicating from CHAR<256 to CHAR<256
+# 2. Replicating from CHAR<256 to CHAR>255
+# 3. Replicating from CHAR>255 to CHAR<256
+# 4. Replicating from CHAR>255 to CHAR>255
+
+# We also make a special case of using the max size of a field on the
+# master, i.e. CHAR(255) in UTF-8, giving another three cases.
+#
+# 5. Replicating UTF-8 CHAR(255) to CHAR(<256)
+# 6. Replicating UTF-8 CHAR(255) to CHAR(>255)
+# 7. Replicating UTF-8 CHAR(255) to CHAR(255) UTF-8
+
+connection master;
+CREATE TABLE t1 (i INT NOT NULL,
+ c CHAR(16) CHARACTER SET utf8 NOT NULL,
+ j INT NOT NULL);
+
+CREATE TABLE t2 (i INT NOT NULL,
+ c CHAR(16) CHARACTER SET utf8 NOT NULL,
+ j INT NOT NULL);
+
+sync_slave_with_master;
+ALTER TABLE t2 MODIFY c CHAR(128) CHARACTER SET utf8 NOT NULL;
+
+connection master;
+CREATE TABLE t3 (i INT NOT NULL,
+ c CHAR(128) CHARACTER SET utf8 NOT NULL,
+ j INT NOT NULL);
+sync_slave_with_master;
+ALTER TABLE t3 MODIFY c CHAR(16) CHARACTER SET utf8 NOT NULL;
+
+connection master;
+CREATE TABLE t4 (i INT NOT NULL,
+ c CHAR(128) CHARACTER SET utf8 NOT NULL,
+ j INT NOT NULL);
+
+CREATE TABLE t5 (i INT NOT NULL,
+ c CHAR(255) CHARACTER SET utf8 NOT NULL,
+ j INT NOT NULL);
+sync_slave_with_master;
+ALTER TABLE t5 MODIFY c CHAR(16) CHARACTER SET utf8 NOT NULL;
+
+connection master;
+CREATE TABLE t6 (i INT NOT NULL,
+ c CHAR(255) CHARACTER SET utf8 NOT NULL,
+ j INT NOT NULL);
+sync_slave_with_master;
+ALTER TABLE t6 MODIFY c CHAR(128) CHARACTER SET utf8 NOT NULL;
+
+connection master;
+CREATE TABLE t7 (i INT NOT NULL,
+ c CHAR(255) CHARACTER SET utf8 NOT NULL,
+ j INT NOT NULL);
+
+--echo [expecting slave to replicate correctly]
+connection master;
+INSERT INTO t1 VALUES (1, "", 1);
+INSERT INTO t1 VALUES (2, repeat(_utf8'a', 16), 2);
+
+let $diff_table_1=master:test.t1;
+let $diff_table_2=slave:test.t1;
+source include/diff_tables.inc;
+
+--echo [expecting slave to replicate correctly]
+connection master;
+INSERT INTO t2 VALUES (1, "", 1);
+INSERT INTO t2 VALUES (2, repeat(_utf8'a', 16), 2);
+
+let $diff_table_1=master:test.t2;
+let $diff_table_2=slave:test.t2;
+source include/diff_tables.inc;
+
+--echo [expecting slave to stop]
+connection master;
+INSERT INTO t3 VALUES (1, "", 1);
+INSERT INTO t3 VALUES (2, repeat(_utf8'a', 128), 2);
+
+connection slave;
+source include/wait_for_slave_sql_to_stop.inc;
+let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
+disable_query_log;
+eval SELECT "$last_error" AS Last_SQL_Error;
+enable_query_log;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=8;
+START SLAVE;
+source include/wait_for_slave_to_start.inc;
+
+--echo [expecting slave to replicate correctly]
+connection master;
+INSERT INTO t4 VALUES (1, "", 1);
+INSERT INTO t4 VALUES (2, repeat(_utf8'a', 128), 2);
+
+let $diff_table_1=master:test.t4;
+let $diff_table_2=slave:test.t4;
+source include/diff_tables.inc;
+
+--echo [expecting slave to stop]
+connection master;
+INSERT INTO t5 VALUES (1, "", 1);
+INSERT INTO t5 VALUES (2, repeat(_utf8'a', 255), 2);
+
+connection slave;
+source include/wait_for_slave_sql_to_stop.inc;
+let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
+disable_query_log;
+eval SELECT "$last_error" AS Last_SQL_Error;
+enable_query_log;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=8;
+START SLAVE;
+source include/wait_for_slave_to_start.inc;
+
+--echo [expecting slave to stop]
+connection master;
+INSERT INTO t6 VALUES (1, "", 1);
+INSERT INTO t6 VALUES (2, repeat(_utf8'a', 255), 2);
+
+connection slave;
+source include/wait_for_slave_sql_to_stop.inc;
+let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
+disable_query_log;
+eval SELECT "$last_error" AS Last_SQL_Error;
+enable_query_log;
+SET GLOBAL SQL_SLAVE_SKIP_COUNTER=8;
+START SLAVE;
+source include/wait_for_slave_to_start.inc;
+
+--echo [expecting slave to replicate correctly]
+connection master;
+INSERT INTO t7 VALUES (1, "", 1);
+INSERT INTO t7 VALUES (2, repeat(_utf8'a', 255), 2);
+
+let $diff_table_1=master:test.t7;
+let $diff_table_2=slave:test.t7;
+source include/diff_tables.inc;
+
+connection master;
+drop table t1, t2, t3, t4, t5, t6, t7;
+sync_slave_with_master;
+