Commit 57184380 authored by Mats Kindahl's avatar Mats Kindahl

WL#5151: Conversion between different types when replicating

Row-based replication requires the types of columns on the
master and slave to be approximately the same (some safe
conversions between strings are allowed), but does not
allow safe conversions between fields of similar types such
as TINYINT and INT.

This patch implement type conversions between similar fields
on the master and slave.

The conversions are controlled using a new variable
SLAVE_TYPE_CONVERSIONS of type SET('ALL_LOSSY','ALL_NON_LOSSY').

Non-lossy conversions are any conversions that do not run the
risk of losing any information, while lossy conversions can
potentially truncate the value. The column definitions are
checked to decide if the conversion is acceptable.

If neither conversion is enabled, it is required that the
definitions of the columns are identical on master and slave.

Conversion is done by creating an internal conversion table,
unpacking the master data into it, and then copy the data to
the real table on the slave.

.bzrignore:
  New files added
client/Makefile.am:
  New files added
client/mysqlbinlog.cc:
  Functions in rpl_utility.cc is now needed by mysqlbinlog.cc.
libmysqld/Makefile.am:
  New files added
mysql-test/extra/rpl_tests/check_type.inc:
  Test include file to check a single type conversion.
mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test:
  Switching to use INT instead of TEXT for column that should not have matching types.
mysql-test/extra/rpl_tests/rpl_row_basic.test:
  Adding code to enable type conversions for BIT tests since InnoDB
  cannot handle them properly due to incorrect information stored as
  metadata.
mysql-test/extra/rpl_tests/type_conversions.test:
  Test file to check a set of type conversions
  with current settings of slave_type_conversions.
mysql-test/suite/rpl/t/rpl_typeconv.test:
  Test file to test conversions from master to slave with
  all possible values for slave_type_conversions.
  
  The test also checks that the slave_type_conversions
  variable works as expected.
sql/field.cc:
  Changing definition of compatible_field_size to both check if 
  two field with identical base types are compatible and give an
  order between them if they are compatible.
  
  This only implement checking on the slave, so it will not affect
  replication from an old master to a new slave.
sql/field.h:
  Changing prototypes for functions:
  - compatible_field_size()
  - init_for_tmp_table()
  - row_pack_length()
sql/log_event.cc:
  Changing compability checks to build a conversion table if the fields
  are compatible, but does not have the same base type.
sql/log_event_old.cc:
  Changing compability checks to build a conversion table if the fields
  are compatible, but does not have the same base type.
sql/mysql_priv.h:
  Adding global option variable for SLAVE_TYPE_CONVERSIONS
sql/mysqld.cc:
  Adding SLAVE_TYPE_CONVERSIONS global server variable.
sql/rpl_record.cc:
  Changing unpack_row to use the conversion table if present.
sql/rpl_rli.h:
  Removing function get_tabledef and replacing it with get_table_data().
  This function retrieve data for table opened for replication, not just
  table definition.
sql/rpl_utility.cc:
  Function table_def::compatible_with is changed to compare table on master
  and slave for compatibility and generate a conversions table if they are
  compatible.
  
  Computing real type of fields from metadata for ENUM and SET types.
  Computing pack_length correctly for ENUM, SET, and BLOB types.
  
  Adding optimization to not check compatibility if no
  slave type conversions are enabled.
sql/rpl_utility.h:
  Changing prototypes since implementation has changed.
  
  Modifying table_def::type() to return real type instead of stored type.
sql/set_var.cc:
  Adding SLAVE_TYPE_CONVERSIONS variable.
sql/set_var.h:
  Adding SLAVE_TYPE_CONVERSIONS variable.
sql/share/errmsg.txt:
  Adding error messages for slave type conversions.
sql/sql_class.h:
  Adding SLAVE_TYPE_CONVERSIONS variable.
sql/sql_select.cc:
  Correcting create_virtual_tmp_table() to compute null bit positions
  correctly in the presence of bit fields.
parent 20674b1a
......@@ -392,6 +392,7 @@ client/rpl_record_old.h
client/rpl_tblmap.h
client/rpl_tblmap.cc
client/rpl_utility.h
client/rpl_utility.cc
client/select_test
client/sql_string.cpp
client/ssl_test
......@@ -1142,6 +1143,7 @@ libmysqld/rpl_filter.cc
libmysqld/rpl_injector.cc
libmysqld/rpl_record.cc
libmysqld/rpl_record_old.cc
libmysqld/rpl_utility.cc
libmysqld/scheduler.cc
libmysqld/set_var.cc
libmysqld/simple-test
......
......@@ -104,9 +104,10 @@ DEFS = -DMYSQL_CLIENT_NO_THREADS \
-DMYSQL_DATADIR="\"$(localstatedir)\""
sql_src=log_event.h mysql_priv.h rpl_constants.h \
rpl_utility.h rpl_tblmap.h rpl_tblmap.cc \
rpl_tblmap.h rpl_tblmap.cc \
log_event.cc my_decimal.h my_decimal.cc \
log_event_old.h log_event_old.cc \
rpl_utility.h rpl_utility.cc \
rpl_record_old.h rpl_record_old.cc
strings_src=decimal.c
......
......@@ -2108,4 +2108,4 @@ int main(int argc, char** argv)
#include "my_decimal.cc"
#include "log_event.cc"
#include "log_event_old.cc"
#include "rpl_utility.cc"
......@@ -55,7 +55,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
item_geofunc.cc item_subselect.cc item_row.cc\
item_xmlfunc.cc \
key.cc lock.cc log.cc sql_state.c \
log_event.cc rpl_record.cc \
log_event.cc rpl_record.cc rpl_utility.cc \
log_event_old.cc rpl_record_old.cc \
protocol.cc net_serv.cc opt_range.cc \
opt_sum.cc procedure.cc records.cc sql_acl.cc \
......
# Helper file to perform one insert of a value into a table with
# different types on master and slave. The file will insert the
# result into the type_conversions table *on the slave* to get a
# summary of failing and succeeding tests.
# Input:
# $source_type Type on the master
# $target_type Type on the slave
# $source_value Value on the master (inserted into the table)
# $target_value Value on the slave (expected value in the table
# on the slave)
# $can_convert True if conversion shall work, false if it
# shall generate an error
connection master;
disable_warnings;
DROP TABLE IF EXISTS t1;
enable_warnings;
eval CREATE TABLE t1 (a $source_type);
sync_slave_with_master;
eval ALTER TABLE t1 MODIFY a $target_type;
connection master;
eval INSERT INTO t1 VALUES($source_value);
if ($can_convert) {
sync_slave_with_master;
eval SELECT a = $target_value into @compare FROM t1;
eval INSERT INTO type_conversions SET
Source = "$source_type",
Target = "$target_type",
Flags = @@slave_type_conversions,
On_Master = $source_value,
Expected = $target_value,
Compare = @compare;
UPDATE type_conversions
SET On_Slave = (SELECT a FROM t1)
WHERE TestNo = LAST_INSERT_ID();
}
if (!$can_convert) {
connection slave;
wait_for_slave_to_stop;
let $error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
eval INSERT INTO type_conversions SET
Source = "$source_type",
Target = "$target_type",
Flags = @@slave_type_conversions,
On_Master = $source_value,
Error = "$error";
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
START SLAVE;
}
......@@ -36,6 +36,9 @@ sync_slave_with_master;
STOP SLAVE;
RESET SLAVE;
SET @saved_slave_type_conversions = @@slave_type_conversions;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY';
eval CREATE TABLE t1 (a INT, b INT PRIMARY KEY, c CHAR(20),
d FLOAT DEFAULT '2.00',
e CHAR(4) DEFAULT 'TEST')
......@@ -62,6 +65,8 @@ SELECT * FROM t1 ORDER BY a;
sync_slave_with_master;
SELECT * FROM t1 ORDER BY a;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
--echo *** Drop t1 ***
connection master;
DROP TABLE t1;
......@@ -495,7 +500,7 @@ sync_slave_with_master;
--echo *** Create t11 on slave ***
STOP SLAVE;
RESET SLAVE;
eval CREATE TABLE t11 (a INT KEY, b BLOB, f TEXT,
eval CREATE TABLE t11 (a INT KEY, b BLOB, f INT,
c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE=$engine_type;
--echo *** Create t11 on Master ***
......
......@@ -6,6 +6,7 @@
# First we test tables with only an index.
#
connection master;
eval CREATE TABLE t1 (C1 CHAR(1), C2 CHAR(1), INDEX (C1)$extra_index_t1) ENGINE = $type ;
SELECT * FROM t1;
sync_slave_with_master;
......@@ -156,6 +157,12 @@ SELECT * FROM t5,t2,t3 WHERE t5.C2='Q' AND t2.c12='R' AND t3.C3 ='S' ORDER BY t5
# Testing special column types
#
if (`select char_length('$bit_field_special') > 0`) {
SET @saved_slave_type_conversions = @@SLAVE_TYPE_CONVERSIONS;
connection slave;
eval SET GLOBAL SLAVE_TYPE_CONVERSIONS = '$bit_field_special';
}
connection master;
eval CREATE TABLE t4 (C1 CHAR(1) PRIMARY KEY, B1 BIT(1), B2 BIT(1) NOT NULL DEFAULT 0, C2 CHAR(1) NOT NULL DEFAULT 'A') ENGINE = $type ;
......@@ -164,6 +171,10 @@ SELECT C1,HEX(B1),HEX(B2) FROM t4 ORDER BY C1;
sync_slave_with_master;
SELECT C1,HEX(B1),HEX(B2) FROM t4 ORDER BY C1;
if (`select char_length('$bit_field_special') > 0`) {
SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
}
#
# Testing conflicting operations
#
......@@ -350,6 +361,10 @@ eval CREATE TABLE t7 (i INT NOT NULL,
c CHAR(255) CHARACTER SET utf8 NOT NULL,
j INT NOT NULL) ENGINE = $type ;
connection slave;
SET @saved_slave_type_conversions = @@slave_type_conversions;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY';
--echo [expecting slave to replicate correctly]
connection master;
INSERT INTO t1 VALUES (1, "", 1);
......@@ -370,17 +385,9 @@ 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 SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
connection master;
RESET MASTER;
connection slave;
......@@ -600,7 +607,15 @@ sync_slave_with_master;
connection master;
# Since t1 contain a bit field, we have to do this trick to handle InnoDB
if (`select char_length('$bit_field_special') > 0`) {
SET @saved_slave_type_conversions = @@SLAVE_TYPE_CONVERSIONS;
connection slave;
eval SET GLOBAL SLAVE_TYPE_CONVERSIONS = '$bit_field_special';
}
--disable_warnings
connection master;
eval CREATE TABLE t1 (a bit) ENGINE=$type;
INSERT IGNORE INTO t1 VALUES (NULL);
INSERT INTO t1 ( a ) VALUES ( 0 );
......@@ -645,6 +660,10 @@ UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 3;
sync_slave_with_master;
if (`select char_length('$bit_field_special') > 0`) {
SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
}
let $diff_table_1=master:test.t1;
let $diff_table_2=slave:test.t1;
source include/diff_tables.inc;
......
This diff is collapsed.
......@@ -4,6 +4,8 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
SET @saved_slave_type_conversions = @@slave_type_conversions;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY';
CREATE DATABASE track;
USE track;
CREATE TABLE `visits` (
......@@ -65,5 +67,6 @@ visits_id myid src ip cc org ref time host entry visit_exit user_id visit_start
SELECT * FROM visits_events;
event_id visit_id timestamp src data visits_events_id
20000 21231038 2007-09-18 03:59:02 Downloads/MySQL-4.1/mysql-4.1.12a-win32.zip 33712207
SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
DROP DATABASE track;
End of 5.1 tests
......@@ -9,6 +9,8 @@ DROP TABLE IF EXISTS t1;
*** Create "wider" table on slave ***
STOP SLAVE;
RESET SLAVE;
SET @saved_slave_type_conversions = @@slave_type_conversions;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY';
CREATE TABLE t1 (
a float (47),
b double (143,9),
......@@ -177,3 +179,4 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
*** Cleanup ***
DROP TABLE t1;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
......@@ -9,6 +9,8 @@ call mtr.add_suppression("Slave: Unknown table 't6' Error_code: 1051");
*** On Slave ***
STOP SLAVE;
RESET SLAVE;
SET @saved_slave_type_conversions = @@slave_type_conversions;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY';
CREATE TABLE t1 (a INT, b INT PRIMARY KEY, c CHAR(20),
d FLOAT DEFAULT '2.00',
e CHAR(4) DEFAULT 'TEST')
......@@ -32,6 +34,7 @@ a b c d e
1 2 TEXAS 2 TEST
2 1 AUSTIN 2 TEST
3 4 QA 2 TEST
SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
*** Drop t1 ***
DROP TABLE t1;
*** Create t2 on slave ***
......@@ -73,8 +76,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 size mismatch - master has size 10, test.t2 on slave has size 6. Master's column size should be <= the slave's column size.
Last_Errno 1641
Last_Error Column 2 of table 'test.t2' cannot be converted from type 'char(10)' to type 'char(5)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -91,8 +94,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 size mismatch - master has size 10, test.t2 on slave has size 6. Master's column size should be <= the slave's column size.
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t2' cannot be converted from type 'char(10)' to type 'char(5)'
STOP SLAVE;
RESET SLAVE;
SELECT * FROM t2 ORDER BY a;
......@@ -140,8 +143,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 0 type mismatch - received type 252, test.t3 has type 3
Last_Errno 1641
Last_Error Column 0 of table 'test.t3' cannot be converted from type 'tinyblob' to type 'int(11)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -158,8 +161,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 0 type mismatch - received type 252, test.t3 has type 3
Last_SQL_Errno 1641
Last_SQL_Error Column 0 of table 'test.t3' cannot be converted from type 'tinyblob' to type 'int(11)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
*** Drop t3 ***
......@@ -202,8 +205,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 0 type mismatch - received type 246, test.t4 has type 3
Last_Errno 1641
Last_Error Column 0 of table 'test.t4' cannot be converted from type 'decimal(8,2)' to type 'int(11)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -220,8 +223,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 0 type mismatch - received type 246, test.t4 has type 3
Last_SQL_Errno 1641
Last_SQL_Error Column 0 of table 'test.t4' cannot be converted from type 'decimal(8,2)' to type 'int(11)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
*** Drop t4 ***
......@@ -264,8 +267,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 5 type mismatch - received type 4, test.t5 has type 246
Last_Errno 1641
Last_Error Column 1 of table 'test.t5' cannot be converted from type 'varchar(6)' to type 'char(5)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -282,8 +285,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 5 type mismatch - received type 4, test.t5 has type 246
Last_SQL_Errno 1641
Last_SQL_Error Column 1 of table 'test.t5' cannot be converted from type 'varchar(6)' to type 'char(5)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
*** Drop t5 ***
......@@ -325,8 +328,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 3 type mismatch - received type 16, test.t6 has type 3
Last_Errno 1641
Last_Error Column 1 of table 'test.t6' cannot be converted from type 'varchar(6)' to type 'char(5)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -343,8 +346,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 3 type mismatch - received type 16, test.t6 has type 3
Last_SQL_Errno 1641
Last_SQL_Error Column 1 of table 'test.t6' cannot be converted from type 'varchar(6)' to type 'char(5)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=3;
*** Drop t6 ***
DROP TABLE t6;
......@@ -493,8 +496,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 254, test.t10 has type 5
Last_Errno 1641
Last_Error Column 2 of table 'test.t10' cannot be converted from type 'char(5)' to type 'double'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -511,8 +514,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 254, test.t10 has type 5
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t10' cannot be converted from type 'char(5)' to type 'double'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
*** Drop t10 ***
......@@ -520,7 +523,7 @@ DROP TABLE t10;
*** Create t11 on slave ***
STOP SLAVE;
RESET SLAVE;
CREATE TABLE t11 (a INT KEY, b BLOB, f TEXT,
CREATE TABLE t11 (a INT KEY, b BLOB, f INT,
c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE='InnoDB';
*** Create t11 on Master ***
CREATE TABLE t11 (a INT PRIMARY KEY, b BLOB, c VARCHAR(254)
......@@ -554,8 +557,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 15, test.t11 has type 252
Last_Errno 1641
Last_Error Column 2 of table 'test.t11' cannot be converted from type 'varchar(254)' to type 'int(11)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -572,8 +575,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 15, test.t11 has type 252
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t11' cannot be converted from type 'varchar(254)' to type 'int(11)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
*** Drop t11 ***
......@@ -944,8 +947,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 0 type mismatch - received type 8, test.t17 has type 2
Last_Errno 1641
Last_Error Column 0 of table 'test.t17' cannot be converted from type 'bigint' to type 'smallint(6)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -962,8 +965,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 0 type mismatch - received type 8, test.t17 has type 2
Last_SQL_Errno 1641
Last_SQL_Error Column 0 of table 'test.t17' cannot be converted from type 'bigint' to type 'smallint(6)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
** DROP table t17 ***
......
......@@ -9,6 +9,8 @@ call mtr.add_suppression("Slave: Unknown table 't6' Error_code: 1051");
*** On Slave ***
STOP SLAVE;
RESET SLAVE;
SET @saved_slave_type_conversions = @@slave_type_conversions;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY';
CREATE TABLE t1 (a INT, b INT PRIMARY KEY, c CHAR(20),
d FLOAT DEFAULT '2.00',
e CHAR(4) DEFAULT 'TEST')
......@@ -32,6 +34,7 @@ a b c d e
1 2 TEXAS 2 TEST
2 1 AUSTIN 2 TEST
3 4 QA 2 TEST
SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
*** Drop t1 ***
DROP TABLE t1;
*** Create t2 on slave ***
......@@ -73,8 +76,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 size mismatch - master has size 10, test.t2 on slave has size 6. Master's column size should be <= the slave's column size.
Last_Errno 1641
Last_Error Column 2 of table 'test.t2' cannot be converted from type 'char(10)' to type 'char(5)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -91,8 +94,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 size mismatch - master has size 10, test.t2 on slave has size 6. Master's column size should be <= the slave's column size.
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t2' cannot be converted from type 'char(10)' to type 'char(5)'
STOP SLAVE;
RESET SLAVE;
SELECT * FROM t2 ORDER BY a;
......@@ -140,8 +143,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 0 type mismatch - received type 252, test.t3 has type 3
Last_Errno 1641
Last_Error Column 0 of table 'test.t3' cannot be converted from type 'tinyblob' to type 'int(11)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -158,8 +161,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 0 type mismatch - received type 252, test.t3 has type 3
Last_SQL_Errno 1641
Last_SQL_Error Column 0 of table 'test.t3' cannot be converted from type 'tinyblob' to type 'int(11)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
*** Drop t3 ***
......@@ -202,8 +205,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 0 type mismatch - received type 246, test.t4 has type 3
Last_Errno 1641
Last_Error Column 0 of table 'test.t4' cannot be converted from type 'decimal(8,2)' to type 'int(11)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -220,8 +223,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 0 type mismatch - received type 246, test.t4 has type 3
Last_SQL_Errno 1641
Last_SQL_Error Column 0 of table 'test.t4' cannot be converted from type 'decimal(8,2)' to type 'int(11)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
*** Drop t4 ***
......@@ -264,8 +267,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 5 type mismatch - received type 4, test.t5 has type 246
Last_Errno 1641
Last_Error Column 1 of table 'test.t5' cannot be converted from type 'varchar(6)' to type 'char(5)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -282,8 +285,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 5 type mismatch - received type 4, test.t5 has type 246
Last_SQL_Errno 1641
Last_SQL_Error Column 1 of table 'test.t5' cannot be converted from type 'varchar(6)' to type 'char(5)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
*** Drop t5 ***
......@@ -325,8 +328,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 3 type mismatch - received type 16, test.t6 has type 3
Last_Errno 1641
Last_Error Column 1 of table 'test.t6' cannot be converted from type 'varchar(6)' to type 'char(5)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -343,8 +346,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 3 type mismatch - received type 16, test.t6 has type 3
Last_SQL_Errno 1641
Last_SQL_Error Column 1 of table 'test.t6' cannot be converted from type 'varchar(6)' to type 'char(5)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=3;
*** Drop t6 ***
DROP TABLE t6;
......@@ -493,8 +496,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 254, test.t10 has type 5
Last_Errno 1641
Last_Error Column 2 of table 'test.t10' cannot be converted from type 'char(5)' to type 'double'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -511,8 +514,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 254, test.t10 has type 5
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t10' cannot be converted from type 'char(5)' to type 'double'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
*** Drop t10 ***
......@@ -520,7 +523,7 @@ DROP TABLE t10;
*** Create t11 on slave ***
STOP SLAVE;
RESET SLAVE;
CREATE TABLE t11 (a INT KEY, b BLOB, f TEXT,
CREATE TABLE t11 (a INT KEY, b BLOB, f INT,
c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE='MyISAM';
*** Create t11 on Master ***
CREATE TABLE t11 (a INT PRIMARY KEY, b BLOB, c VARCHAR(254)
......@@ -554,8 +557,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 15, test.t11 has type 252
Last_Errno 1641
Last_Error Column 2 of table 'test.t11' cannot be converted from type 'varchar(254)' to type 'int(11)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -572,8 +575,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 15, test.t11 has type 252
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t11' cannot be converted from type 'varchar(254)' to type 'int(11)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
*** Drop t11 ***
......@@ -944,8 +947,8 @@ Replicate_Do_Table
Replicate_Ignore_Table #
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 0 type mismatch - received type 8, test.t17 has type 2
Last_Errno 1641
Last_Error Column 0 of table 'test.t17' cannot be converted from type 'bigint' to type 'smallint(6)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -962,8 +965,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 0 type mismatch - received type 8, test.t17 has type 2
Last_SQL_Errno 1641
Last_SQL_Error Column 0 of table 'test.t17' cannot be converted from type 'bigint' to type 'smallint(6)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
** DROP table t17 ***
......
......@@ -563,8 +563,8 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254
Last_Errno 1641
Last_Error Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -581,8 +581,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......@@ -638,8 +638,8 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15
Last_Errno 1641
Last_Error Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -656,8 +656,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......@@ -1704,8 +1704,8 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254
Last_Errno 1641
Last_Error Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -1722,8 +1722,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......@@ -1779,8 +1779,8 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15
Last_Errno 1641
Last_Error Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -1797,8 +1797,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......@@ -2845,8 +2845,8 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254
Last_Errno 1641
Last_Error Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -2863,8 +2863,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......@@ -2920,8 +2920,8 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15
Last_Errno 1641
Last_Error Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -2938,8 +2938,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......
......@@ -563,8 +563,8 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254
Last_Errno 1641
Last_Error Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -581,8 +581,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......@@ -638,8 +638,8 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15
Last_Errno 1641
Last_Error Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -656,8 +656,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......@@ -1704,8 +1704,8 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254
Last_Errno 1641
Last_Error Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -1722,8 +1722,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......@@ -1779,8 +1779,8 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15
Last_Errno 1641
Last_Error Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -1797,8 +1797,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......@@ -2845,8 +2845,8 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254
Last_Errno 1641
Last_Error Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -2863,8 +2863,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......@@ -2920,8 +2920,8 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15
Last_Errno 1641
Last_Error Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)'
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
......@@ -2938,8 +2938,8 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno #
Last_IO_Error #
Last_SQL_Errno 1535
Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15
Last_SQL_Errno 1641
Last_SQL_Error Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)'
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......
......@@ -476,6 +476,8 @@ ALTER TABLE t6 MODIFY c CHAR(128) CHARACTER SET utf8 NOT NULL;
CREATE TABLE t7 (i INT NOT NULL,
c CHAR(255) CHARACTER SET utf8 NOT NULL,
j INT NOT NULL) ENGINE = 'MYISAM' ;
SET @saved_slave_type_conversions = @@slave_type_conversions;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY';
[expecting slave to replicate correctly]
INSERT INTO t1 VALUES (1, "", 1);
INSERT INTO t1 VALUES (2, repeat(_utf8'a', 16), 2);
......@@ -484,11 +486,7 @@ Comparing tables master:test.t1 and slave:test.t1
INSERT INTO t2 VALUES (1, "", 1);
INSERT INTO t2 VALUES (2, repeat(_utf8'a', 16), 2);
Comparing tables master:test.t2 and slave:test.t2
[expecting slave to stop]
INSERT INTO t3 VALUES (1, "", 1);
INSERT INTO t3 VALUES (2, repeat(_utf8'a', 128), 2);
Last_SQL_Error
Table definition on master and slave does not match: Column 1 size mismatch - master has size 384, test.t3 on slave has size 49. Master's column size should be <= the slave's column size.
SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
RESET MASTER;
STOP SLAVE;
RESET SLAVE;
......@@ -501,7 +499,7 @@ Comparing tables master:test.t4 and slave:test.t4
INSERT INTO t5 VALUES (1, "", 1);
INSERT INTO t5 VALUES (2, repeat(_utf8'a', 255), 2);
Last_SQL_Error
Table definition on master and slave does not match: Column 1 size mismatch - master has size 765, test.t5 on slave has size 49. Master's column size should be <= the slave's column size.
Column 1 of table 'test.t5' cannot be converted from type 'char(255)' to type 'char(16)'
RESET MASTER;
STOP SLAVE;
RESET SLAVE;
......@@ -510,7 +508,7 @@ START SLAVE;
INSERT INTO t6 VALUES (1, "", 1);
INSERT INTO t6 VALUES (2, repeat(_utf8'a', 255), 2);
Last_SQL_Error
Table definition on master and slave does not match: Column 1 size mismatch - master has size 765, test.t6 on slave has size 385. Master's column size should be <= the slave's column size.
Column 1 of table 'test.t6' cannot be converted from type 'char(255)' to type 'char(128)'
RESET MASTER;
STOP SLAVE;
RESET SLAVE;
......
......@@ -354,6 +354,8 @@ X Q 5 7 R 49 X Y 2 S 1
X Q 5 7 R 49 X Z 2 S 2
X Q 5 9 R 81 X Y 2 S 1
X Q 5 9 R 81 X Z 2 S 2
SET @saved_slave_type_conversions = @@SLAVE_TYPE_CONVERSIONS;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_LOSSY';
CREATE TABLE t4 (C1 CHAR(1) PRIMARY KEY, B1 BIT(1), B2 BIT(1) NOT NULL DEFAULT 0, C2 CHAR(1) NOT NULL DEFAULT 'A') ENGINE = 'INNODB' ;
INSERT INTO t4 SET C1 = 1;
SELECT C1,HEX(B1),HEX(B2) FROM t4 ORDER BY C1;
......@@ -362,6 +364,7 @@ C1 HEX(B1) HEX(B2)
SELECT C1,HEX(B1),HEX(B2) FROM t4 ORDER BY C1;
C1 HEX(B1) HEX(B2)
1 NULL 0
SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
CREATE TABLE t7 (C1 INT PRIMARY KEY, C2 INT) ENGINE = 'INNODB' ;
--- on slave: original values ---
INSERT INTO t7 VALUES (1,3), (2,6), (3,9);
......@@ -476,6 +479,8 @@ ALTER TABLE t6 MODIFY c CHAR(128) CHARACTER SET utf8 NOT NULL;
CREATE TABLE t7 (i INT NOT NULL,
c CHAR(255) CHARACTER SET utf8 NOT NULL,
j INT NOT NULL) ENGINE = 'INNODB' ;
SET @saved_slave_type_conversions = @@slave_type_conversions;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY';
[expecting slave to replicate correctly]
INSERT INTO t1 VALUES (1, "", 1);
INSERT INTO t1 VALUES (2, repeat(_utf8'a', 16), 2);
......@@ -484,11 +489,7 @@ Comparing tables master:test.t1 and slave:test.t1
INSERT INTO t2 VALUES (1, "", 1);
INSERT INTO t2 VALUES (2, repeat(_utf8'a', 16), 2);
Comparing tables master:test.t2 and slave:test.t2
[expecting slave to stop]
INSERT INTO t3 VALUES (1, "", 1);
INSERT INTO t3 VALUES (2, repeat(_utf8'a', 128), 2);
Last_SQL_Error
Table definition on master and slave does not match: Column 1 size mismatch - master has size 384, test.t3 on slave has size 49. Master's column size should be <= the slave's column size.
SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
RESET MASTER;
STOP SLAVE;
RESET SLAVE;
......@@ -501,7 +502,7 @@ Comparing tables master:test.t4 and slave:test.t4
INSERT INTO t5 VALUES (1, "", 1);
INSERT INTO t5 VALUES (2, repeat(_utf8'a', 255), 2);
Last_SQL_Error
Table definition on master and slave does not match: Column 1 size mismatch - master has size 765, test.t5 on slave has size 49. Master's column size should be <= the slave's column size.
Column 1 of table 'test.t5' cannot be converted from type 'char(255)' to type 'char(16)'
RESET MASTER;
STOP SLAVE;
RESET SLAVE;
......@@ -510,7 +511,7 @@ START SLAVE;
INSERT INTO t6 VALUES (1, "", 1);
INSERT INTO t6 VALUES (2, repeat(_utf8'a', 255), 2);
Last_SQL_Error
Table definition on master and slave does not match: Column 1 size mismatch - master has size 765, test.t6 on slave has size 385. Master's column size should be <= the slave's column size.
Column 1 of table 'test.t6' cannot be converted from type 'char(255)' to type 'char(128)'
RESET MASTER;
STOP SLAVE;
RESET SLAVE;
......@@ -597,6 +598,8 @@ UPDATE t1 SET a = 0 WHERE a < 4;
UPDATE t1 SET a = 8 WHERE a < 5;
Comparing tables master:test.t1 and slave:test.t1
drop table t1;
SET @saved_slave_type_conversions = @@SLAVE_TYPE_CONVERSIONS;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_LOSSY';
CREATE TABLE t1 (a bit) ENGINE='INNODB' ;
INSERT IGNORE INTO t1 VALUES (NULL);
INSERT INTO t1 ( a ) VALUES ( 0 );
......@@ -637,5 +640,6 @@ DELETE FROM t1 WHERE a < 3 LIMIT 0;
UPDATE t1 SET a = 8 WHERE a = 5 LIMIT 2;
INSERT INTO t1 ( a ) VALUES ( 1 );
UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 3;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
Comparing tables master:test.t1 and slave:test.t1
drop table t1;
......@@ -216,7 +216,7 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Errno 1641
Last_Error <Last_Error>
Skip_Counter 0
Exec_Master_Log_Pos #
......@@ -234,7 +234,7 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno <Last_IO_Errno>
Last_IO_Error <Last_IO_Error>
Last_SQL_Errno 1535
Last_SQL_Errno 1641
Last_SQL_Error <Last_SQL_Error>
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......@@ -259,7 +259,7 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Errno 1641
Last_Error <Last_Error>
Skip_Counter 0
Exec_Master_Log_Pos #
......@@ -277,7 +277,7 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno <Last_IO_Errno>
Last_IO_Error <Last_IO_Error>
Last_SQL_Errno 1535
Last_SQL_Errno 1641
Last_SQL_Error <Last_SQL_Error>
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......@@ -302,7 +302,7 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Errno 1641
Last_Error <Last_Error>
Skip_Counter 0
Exec_Master_Log_Pos #
......@@ -320,7 +320,7 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno <Last_IO_Errno>
Last_IO_Error <Last_IO_Error>
Last_SQL_Errno 1535
Last_SQL_Errno 1641
Last_SQL_Error <Last_SQL_Error>
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......
......@@ -216,7 +216,7 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Errno 1641
Last_Error <Last_Error>
Skip_Counter 0
Exec_Master_Log_Pos #
......@@ -234,7 +234,7 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno <Last_IO_Errno>
Last_IO_Error <Last_IO_Error>
Last_SQL_Errno 1535
Last_SQL_Errno 1641
Last_SQL_Error <Last_SQL_Error>
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......@@ -259,7 +259,7 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Errno 1641
Last_Error <Last_Error>
Skip_Counter 0
Exec_Master_Log_Pos #
......@@ -277,7 +277,7 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno <Last_IO_Errno>
Last_IO_Error <Last_IO_Error>
Last_SQL_Errno 1535
Last_SQL_Errno 1641
Last_SQL_Error <Last_SQL_Error>
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......@@ -302,7 +302,7 @@ Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1535
Last_Errno 1641
Last_Error <Last_Error>
Skip_Counter 0
Exec_Master_Log_Pos #
......@@ -320,7 +320,7 @@ Seconds_Behind_Master #
Master_SSL_Verify_Server_Cert No
Last_IO_Errno <Last_IO_Errno>
Last_IO_Error <Last_IO_Error>
Last_SQL_Errno 1535
Last_SQL_Errno 1641
Last_SQL_Error <Last_SQL_Error>
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
......
This diff is collapsed.
source include/master-slave.inc;
SET @saved_slave_type_conversions = @@slave_type_conversions;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY';
CREATE DATABASE track;
USE track;
......@@ -130,7 +133,10 @@ VALUES ('3m3l4rhs6do0sf5p1i9lr94g928a272v', '', '', INET_ATON('71.118.124.98'),
SELECT * FROM visits;
SELECT * FROM visits_events;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
# Cleanup
DROP DATABASE track;
sync_slave_with_master;
--echo End of 5.1 tests
......@@ -18,6 +18,9 @@ sync_slave_with_master;
STOP SLAVE;
RESET SLAVE;
SET @saved_slave_type_conversions = @@slave_type_conversions;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY';
eval CREATE TABLE t1 (
a float (47),
b double (143,9),
......@@ -217,4 +220,6 @@ connection master;
DROP TABLE t1;
sync_slave_with_master;
SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions;
# END 5.1 Test Case
......@@ -2,6 +2,8 @@
-- source include/have_binlog_format_row.inc
-- source include/master-slave.inc
connection slave;
let $bit_field_special = ALL_LOSSY;
let $type= 'INNODB' ;
let $extra_index= ;
-- source extra/rpl_tests/rpl_row_basic.test
......
--source include/have_binlog_format_row.inc
--source include/master-slave.inc
connection slave;
set @saved_slave_type_conversions = @@global.slave_type_conversions;
CREATE TABLE type_conversions (
TestNo INT AUTO_INCREMENT PRIMARY KEY,
Source TEXT,
Target TEXT,
Flags TEXT,
On_Master TEXT,
On_Slave TEXT,
Expected TEXT,
Compare INT,
Error TEXT);
SELECT @@global.slave_type_conversions;
SET GLOBAL SLAVE_TYPE_CONVERSIONS='';
SELECT @@global.slave_type_conversions;
SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_NON_LOSSY';
SELECT @@global.slave_type_conversions;
SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_LOSSY';
SELECT @@global.slave_type_conversions;
SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_LOSSY,ALL_NON_LOSSY';
SELECT @@global.slave_type_conversions;
--error ER_WRONG_VALUE_FOR_VAR
SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_LOSSY,ALL_NON_LOSSY,NONEXISTING_BIT';
SELECT @@global.slave_type_conversions;
# Checking strict interpretation of type conversions
connection slave;
SET GLOBAL SLAVE_TYPE_CONVERSIONS='';
source extra/rpl_tests/type_conversions.test;
# Checking lossy integer type conversions
connection slave;
SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_NON_LOSSY';
source extra/rpl_tests/type_conversions.test;
# Checking non-lossy integer type conversions
connection slave;
SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_LOSSY';
source extra/rpl_tests/type_conversions.test;
# Checking all type conversions
connection slave;
SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_LOSSY,ALL_NON_LOSSY';
source extra/rpl_tests/type_conversions.test;
connection slave;
--echo **** Result of conversions ****
disable_query_log;
SELECT RPAD(Source, 15, ' ') AS Source_Type,
RPAD(Target, 15, ' ') AS Target_Type,
RPAD(Flags, 25, ' ') AS All_Type_Conversion_Flags,
IF(Compare IS NULL AND Error IS NOT NULL, '<Correct error>',
IF(Compare, '<Correct value>',
CONCAT("'", On_Slave, "' != '", Expected, "'")))
AS Value_On_Slave
FROM type_conversions;
enable_query_log;
DROP TABLE type_conversions;
connection master;
DROP TABLE t1;
sync_slave_with_master;
set global slave_type_conversions = @saved_slave_type_conversions;
This diff is collapsed.
......@@ -164,22 +164,13 @@ class Field
table, which is located on disk).
*/
virtual uint32 pack_length_in_rec() const { return pack_length(); }
virtual int compatible_field_size(uint field_metadata,
const Relay_log_info *);
virtual bool compatible_field_size(uint metadata, Relay_log_info *rli,
int *order);
virtual uint pack_length_from_metadata(uint field_metadata)
{ return field_metadata; }
/*
This method is used to return the size of the data in a row-based
replication row record. The default implementation of returning 0 is
designed to allow fields that do not use metadata to return TRUE (1)
from compatible_field_size() which uses this function in the comparison.
The default value for field metadata for fields that do not have
metadata is 0. Thus, 0 == 0 means the fields are compatible in size.
Note: While most classes that override this method return pack_length(),
the classes Field_string, Field_varstring, and Field_blob return
field_length + 1, field_length, and pack_length_no_ptr() respectfully.
*/
{
DBUG_ENTER("Field::pack_length_from_metadata");
DBUG_RETURN(field_metadata);
}
virtual uint row_pack_length() { return 0; }
virtual int save_field_metadata(uchar *first_byte)
{ return do_save_field_metadata(first_byte); }
......@@ -636,6 +627,13 @@ class Field_num :public Field {
int store_decimal(const my_decimal *);
my_decimal *val_decimal(my_decimal *);
uint is_equal(Create_field *new_field);
uint row_pack_length() { return pack_length(); }
uint32 pack_length_from_metadata(uint field_metadata) {
uint32 length= pack_length();
DBUG_PRINT("result", ("pack_length_from_metadata(%d): %u",
field_metadata, length));
return length;
}
int check_int(CHARSET_INFO *cs, const char *str, int length,
const char *int_end, int error);
bool get_int(CHARSET_INFO *cs, const char *from, uint len,
......@@ -806,8 +804,8 @@ class Field_new_decimal :public Field_num {
uint32 pack_length() const { return (uint32) bin_size; }
uint pack_length_from_metadata(uint field_metadata);
uint row_pack_length() { return pack_length(); }
int compatible_field_size(uint field_metadata,
const Relay_log_info *rli);
bool compatible_field_size(uint field_metadata, Relay_log_info *rli,
int *order_var);
uint is_equal(Create_field *new_field);
virtual const uchar *unpack(uchar* to, const uchar *from,
uint param_data, bool low_byte_first);
......@@ -1501,9 +1499,9 @@ class Field_string :public Field_longstr {
return row_pack_length();
return (((field_metadata >> 4) & 0x300) ^ 0x300) + (field_metadata & 0x00ff);
}
int compatible_field_size(uint field_metadata,
const Relay_log_info *rli);
uint row_pack_length() { return (field_length + 1); }
bool compatible_field_size(uint field_metadata, Relay_log_info *rli,
int *order_var);
uint row_pack_length() { return field_length; }
int pack_cmp(const uchar *a,const uchar *b,uint key_length,
my_bool insert_or_update);
int pack_cmp(const uchar *b,uint key_length,my_bool insert_or_update);
......@@ -1965,8 +1963,8 @@ class Field_bit :public Field {
uint pack_length_from_metadata(uint field_metadata);
uint row_pack_length()
{ return (bytes_in_rec + ((bit_len > 0) ? 1 : 0)); }
int compatible_field_size(uint field_metadata,
const Relay_log_info *rli);
bool compatible_field_size(uint metadata, Relay_log_info *rli,
int *order_var);
void sql_type(String &str) const;
virtual uchar *pack(uchar *to, const uchar *from,
uint max_length, bool low_byte_first);
......@@ -2069,7 +2067,8 @@ class Create_field :public Sql_alloc
/* Init for a tmp table field. To be extended if need be. */
void init_for_tmp_table(enum_field_types sql_type_arg,
uint32 max_length, uint32 decimals,
bool maybe_null, bool is_unsigned);
bool maybe_null, bool is_unsigned,
uint pack_length = ~0U);
bool init(THD *thd, char *field_name, enum_field_types type, char *length,
char *decimals, uint type_modifier, Item *default_value,
......
......@@ -29,7 +29,6 @@
#include "rpl_rli.h"
#include "rpl_mi.h"
#include "rpl_filter.h"
#include "rpl_utility.h"
#include "rpl_record.h"
#include <my_dir.h>
......@@ -37,6 +36,7 @@
#include <base64.h>
#include <my_bitmap.h>
#include "rpl_utility.h"
#define log_cs &my_charset_latin1
......@@ -7309,11 +7309,18 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
*/
{
DBUG_PRINT("debug", ("Checking compability of tables to lock - tables_to_lock: %p",
rli->tables_to_lock));
RPL_TABLE_LIST *ptr= rli->tables_to_lock;
for ( ; ptr ; ptr= static_cast<RPL_TABLE_LIST*>(ptr->next_global))
{
if (ptr->m_tabledef.compatible_with(rli, ptr->table))
TABLE *conv_table;
if (!ptr->m_tabledef.compatible_with(thd, const_cast<Relay_log_info*>(rli),
ptr->table, &conv_table))
{
DBUG_PRINT("debug", ("Table: %s.%s is not compatible with master",
ptr->table->s->db.str,
ptr->table->s->table_name.str));
/*
We should not honour --slave-skip-errors at this point as we are
having severe errors which should not be skiped.
......@@ -7324,12 +7331,17 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
const_cast<Relay_log_info*>(rli)->clear_tables_to_lock();
DBUG_RETURN(ERR_BAD_TABLE_DEF);
}
DBUG_PRINT("debug", ("Table: %s.%s is compatible with master"
" - conv_table: %p",
ptr->table->s->db.str,
ptr->table->s->table_name.str, conv_table));
ptr->m_conv_table= conv_table;
}
}
/*
... and then we add all the tables to the table map and remove
them from tables to lock.
... and then we add all the tables to the table map and but keep
them in the tables to lock list.
We also invalidate the query cache for all the tables, since
they will now be changed.
......@@ -7825,7 +7837,10 @@ int Table_map_log_event::save_field_metadata()
DBUG_ENTER("Table_map_log_event::save_field_metadata");
int index= 0;
for (unsigned int i= 0 ; i < m_table->s->fields ; i++)
{
DBUG_PRINT("debug", ("field_type: %d", m_coltype[i]));
index+= m_table->s->field[i]->save_field_metadata(&m_field_metadata[index]);
}
DBUG_RETURN(index);
}
#endif /* !defined(MYSQL_CLIENT) */
......
......@@ -107,14 +107,24 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
RPL_TABLE_LIST *ptr= rli->tables_to_lock;
for ( ; ptr ; ptr= static_cast<RPL_TABLE_LIST*>(ptr->next_global))
{
if (ptr->m_tabledef.compatible_with(rli, ptr->table))
TABLE *conv_table;
if (!ptr->m_tabledef.compatible_with(thd, const_cast<Relay_log_info*>(rli),
ptr->table, &conv_table))
{
DBUG_PRINT("debug", ("Table: %s.%s is not compatible with master",
ptr->table->s->db.str,
ptr->table->s->table_name.str));
mysql_unlock_tables(thd, thd->lock);
thd->lock= 0;
thd->is_slave_error= 1;
const_cast<Relay_log_info*>(rli)->clear_tables_to_lock();
DBUG_RETURN(Old_rows_log_event::ERR_BAD_TABLE_DEF);
}
DBUG_PRINT("debug", ("Table: %s.%s is compatible with master"
" - conv_table: %p",
ptr->table->s->db.str,
ptr->table->s->table_name.str, conv_table));
ptr->m_conv_table= conv_table;
}
}
......@@ -1578,7 +1588,9 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli)
RPL_TABLE_LIST *ptr= rli->tables_to_lock;
for ( ; ptr ; ptr= static_cast<RPL_TABLE_LIST*>(ptr->next_global))
{
if (ptr->m_tabledef.compatible_with(rli, ptr->table))
TABLE *conv_table;
if (ptr->m_tabledef.compatible_with(thd, const_cast<Relay_log_info*>(rli),
ptr->table, &conv_table))
{
mysql_unlock_tables(thd, thd->lock);
thd->lock= 0;
......@@ -1586,12 +1598,14 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli)
const_cast<Relay_log_info*>(rli)->clear_tables_to_lock();
DBUG_RETURN(ERR_BAD_TABLE_DEF);
}
ptr->m_conv_table= conv_table;
}
}
/*
... and then we add all the tables to the table map and remove
them from tables to lock.
... and then we add all the tables to the table map but keep
them in the tables to lock list.
We also invalidate the query cache for all the tables, since
they will now be changed.
......
......@@ -1998,6 +1998,7 @@ extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap;
extern my_bool opt_slave_compressed_protocol, use_temp_pool;
extern ulong slave_exec_mode_options;
extern ulong slave_type_conversions_options;
extern my_bool opt_readonly, lower_case_file_system;
extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
extern my_bool opt_secure_auth;
......
......@@ -525,6 +525,8 @@ ulong open_files_limit, max_binlog_size, max_relay_log_size;
ulong slave_net_timeout, slave_trans_retries;
ulong slave_exec_mode_options;
const char *slave_exec_mode_str= "STRICT";
ulong slave_type_conversions_options;
const char *slave_type_conversions_default= "";
ulong thread_cache_size=0, thread_pool_size= 0;
ulong binlog_cache_size=0;
ulonglong max_binlog_cache_size=0;
......@@ -5690,6 +5692,7 @@ enum options_mysqld
#endif /* defined(ENABLED_DEBUG_SYNC) */
OPT_OLD_MODE,
OPT_SLAVE_EXEC_MODE,
OPT_SLAVE_TYPE_CONVERSIONS,
OPT_GENERAL_LOG_FILE,
OPT_SLOW_QUERY_LOG_FILE,
OPT_IGNORE_BUILTIN_INNODB
......@@ -6413,6 +6416,15 @@ replicating a LOAD DATA INFILE command.",
{"slave-exec-mode", OPT_SLAVE_EXEC_MODE,
"Modes for how replication events should be executed. Legal values are STRICT (default) and IDEMPOTENT. In IDEMPOTENT mode, replication will not stop for operations that are idempotent. In STRICT mode, replication will stop on any unexpected difference between the master and the slave.",
(uchar**) &slave_exec_mode_str, (uchar**) &slave_exec_mode_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"slave-type-conversions", OPT_SLAVE_TYPE_CONVERSIONS,
"Set of slave type conversions that are enabled. Legal values are:"
" ALL_LOSSY to enable lossy conversions and"
" ALL_NON_LOSSY to enable non-lossy conversions."
" If the variable is assigned the empty set, no conversions are"
" allowed and it is expected that the types match exactly.",
(uchar**) &slave_type_conversions_default,
(uchar**) &slave_type_conversions_default,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"slow-query-log", OPT_SLOW_LOG,
"Enable|disable slow query log", (uchar**) &opt_slow_log,
......@@ -7671,6 +7683,11 @@ static int mysql_init_variables(void)
slave_exec_mode_options= (uint)
find_bit_type_or_exit(slave_exec_mode_str, &slave_exec_mode_typelib, NULL,
&error);
/* Slave type conversions */
slave_type_conversions_options= 0;
slave_type_conversions_options=
find_bit_type_or_exit(slave_type_conversions_default, &slave_type_conversions_typelib,
NULL, &error);
if (error)
return 1;
opt_specialflag= SPECIAL_ENGLISH;
......@@ -7900,6 +7917,12 @@ mysqld_get_one_option(int optid,
if (error)
return 1;
break;
case OPT_SLAVE_TYPE_CONVERSIONS:
slave_type_conversions_options= (uint)
find_bit_type_or_exit(argument, &slave_type_conversions_typelib, "", &error);
if (error)
return 1;
break;
#endif
case OPT_SAFEMALLOC_MEM_LIMIT:
#if !defined(DBUG_OFF) && defined(SAFEMALLOC)
......
......@@ -104,10 +104,10 @@ pack_row(TABLE *table, MY_BITMAP const* cols,
#endif
pack_ptr= field->pack(pack_ptr, field->ptr + offset,
field->max_data_length(), TRUE);
DBUG_PRINT("debug", ("field: %s; pack_ptr: 0x%lx;"
DBUG_PRINT("debug", ("field: %s; real_type: %d, pack_ptr: 0x%lx;"
" pack_ptr':0x%lx; bytes: %d",
field->field_name, (ulong) old_pack_ptr,
(ulong) pack_ptr,
field->field_name, field->real_type(),
(ulong) old_pack_ptr, (ulong) pack_ptr,
(int) (pack_ptr - old_pack_ptr)));
}
......@@ -201,10 +201,30 @@ unpack_row(Relay_log_info const *rli,
// The "current" null bits
unsigned int null_bits= *null_ptr++;
uint i= 0;
table_def *tabledef= ((Relay_log_info*)rli)->get_tabledef(table);
table_def *tabledef;
TABLE *conv_table;
bool table_found= rli->get_table_data(table, &tabledef, &conv_table);
DBUG_PRINT("debug", ("Table data: table_found: %d, tabldef: %p, conv_table: %p",
table_found, tabledef, conv_table));
DBUG_ASSERT(table_found);
if (!table_found)
return HA_ERR_GENERIC;
for (field_ptr= begin_ptr ; field_ptr < end_ptr && *field_ptr ; ++field_ptr)
{
Field *const f= *field_ptr;
/*
If there is a conversion table, we pick up the field pointer to
the conversion table. If the conversion table or the field
pointer is NULL, no conversions are necessary.
*/
Field *conv_field=
conv_table ? conv_table->field[field_ptr - begin_ptr] : NULL;
Field *const f=
conv_field ? conv_field : *field_ptr;
DBUG_PRINT("debug", ("Conversion %srequired for field '%s' (#%d)",
conv_field ? "" : "not ",
(*field_ptr)->field_name, field_ptr - begin_ptr));
DBUG_ASSERT(f != NULL);
/*
No need to bother about columns that does not exist: they have
......@@ -247,6 +267,39 @@ unpack_row(Relay_log_info const *rli,
(int) (pack_ptr - old_pack_ptr)));
}
/*
If conv_field is set, then we are doing a conversion. In this
case, we have unpacked the master data to the conversion
table, so we need to copy the value stored in the conversion
table into the final table and do the conversion at the same time.
*/
if (conv_field)
{
Copy_field copy;
#ifndef DBUG_OFF
char source_buf[MAX_FIELD_WIDTH];
char value_buf[MAX_FIELD_WIDTH];
String source_type(source_buf, sizeof(source_buf), system_charset_info);
String value_string(value_buf, sizeof(value_buf), system_charset_info);
conv_field->sql_type(source_type);
conv_field->val_str(&value_string);
DBUG_PRINT("debug", ("Copying field '%s' of type '%s' with value '%s'",
(*field_ptr)->field_name,
source_type.c_ptr(), value_string.c_ptr()));
#endif
copy.set(*field_ptr, f, TRUE);
(*copy.do_copy)(&copy);
#ifndef DBUG_OFF
char target_buf[MAX_FIELD_WIDTH];
String target_type(target_buf, sizeof(target_buf), system_charset_info);
(*field_ptr)->sql_type(target_type);
(*field_ptr)->val_str(&value_string);
DBUG_PRINT("debug", ("Value of field '%s' of type '%s' is now '%s'",
(*field_ptr)->field_name,
target_type.c_ptr(), value_string.c_ptr()));
#endif
}
null_mask <<= 1;
}
i++;
......
......@@ -314,13 +314,21 @@ class Relay_log_info : public Slave_reporting_capability
uint tables_to_lock_count; /* RBR: Count of tables to lock */
table_mapping m_table_map; /* RBR: Mapping table-id to table */
inline table_def *get_tabledef(TABLE *tbl)
bool get_table_data(TABLE *table_arg, table_def **tabledef_var, TABLE **conv_table_var) const
{
table_def *td= 0;
for (TABLE_LIST *ptr= tables_to_lock; ptr && !td; ptr= ptr->next_global)
if (ptr->table == tbl)
td= &((RPL_TABLE_LIST *)ptr)->m_tabledef;
return (td);
DBUG_ASSERT(tabledef_var && conv_table_var);
for (TABLE_LIST *ptr= tables_to_lock ; ptr != NULL ; ptr= ptr->next_global)
if (ptr->table == table_arg)
{
*tabledef_var= &static_cast<RPL_TABLE_LIST*>(ptr)->m_tabledef;
*conv_table_var= static_cast<RPL_TABLE_LIST*>(ptr)->m_conv_table;
DBUG_PRINT("debug", ("Fetching table data for table %s.%s:"
" tabledef: %p, conv_table: %p",
table_arg->s->db.str, table_arg->s->table_name.str,
*tabledef_var, *conv_table_var));
return true;
}
return false;
}
/*
......
This diff is collapsed.
......@@ -21,6 +21,7 @@
#endif
#include "mysql_priv.h"
#include "mysql_com.h"
class Relay_log_info;
......@@ -43,116 +44,19 @@ class Relay_log_info;
class table_def
{
public:
/**
Convenience declaration of the type of the field type data in a
table map event.
*/
typedef unsigned char field_type;
/**
Constructor.
@param types Array of types
@param types Array of types, each stored as a byte
@param size Number of elements in array 'types'
@param field_metadata Array of extra information about fields
@param metadata_size Size of the field_metadata array
@param null_bitmap The bitmap of fields that can be null
*/
table_def(field_type *types, ulong size, uchar *field_metadata,
int metadata_size, uchar *null_bitmap)
: m_size(size), m_type(0), m_field_metadata_size(metadata_size),
m_field_metadata(0), m_null_bits(0), m_memory(NULL)
{
m_memory= (uchar *)my_multi_malloc(MYF(MY_WME),
&m_type, size,
&m_field_metadata,
size * sizeof(uint16),
&m_null_bits, (size + 7) / 8,
NULL);
table_def(unsigned char *types, ulong size, uchar *field_metadata,
int metadata_size, uchar *null_bitmap);
bzero(m_field_metadata, size * sizeof(uint16));
if (m_type)
memcpy(m_type, types, size);
else
m_size= 0;
/*
Extract the data from the table map into the field metadata array
iff there is field metadata. The variable metadata_size will be
0 if we are replicating from an older version server since no field
metadata was written to the table map. This can also happen if
there were no fields in the master that needed extra metadata.
*/
if (m_size && metadata_size)
{
int index= 0;
for (unsigned int i= 0; i < m_size; i++)
{
switch (m_type[i]) {
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_DOUBLE:
case MYSQL_TYPE_FLOAT:
{
/*
These types store a single byte.
*/
m_field_metadata[i]= field_metadata[index];
index++;
break;
}
case MYSQL_TYPE_SET:
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_STRING:
{
uint16 x= field_metadata[index++] << 8U; // real_type
x+= field_metadata[index++]; // pack or field length
m_field_metadata[i]= x;
break;
}
case MYSQL_TYPE_BIT:
{
uint16 x= field_metadata[index++];
x = x + (field_metadata[index++] << 8U);
m_field_metadata[i]= x;
break;
}
case MYSQL_TYPE_VARCHAR:
{
/*
These types store two bytes.
*/
char *ptr= (char *)&field_metadata[index];
m_field_metadata[i]= uint2korr(ptr);
index= index + 2;
break;
}
case MYSQL_TYPE_NEWDECIMAL:
{
uint16 x= field_metadata[index++] << 8U; // precision
x+= field_metadata[index++]; // decimals
m_field_metadata[i]= x;
break;
}
default:
m_field_metadata[i]= 0;
break;
}
}
}
if (m_size && null_bitmap)
memcpy(m_null_bits, null_bitmap, (m_size + 7) / 8);
}
~table_def() {
my_free(m_memory, MYF(0));
#ifndef DBUG_OFF
m_type= 0;
m_size= 0;
#endif
}
~table_def();
/**
Return the number of fields there is type data for.
......@@ -171,10 +75,40 @@ class table_def
<code>index</code>. Currently, only the type identifier is
returned.
*/
field_type type(ulong index) const
enum_field_types type(ulong index) const
{
DBUG_ASSERT(index < m_size);
return m_type[index];
/*
If the source type is MYSQL_TYPE_STRING, it can in reality be
either MYSQL_TYPE_STRING, MYSQL_TYPE_ENUM, or MYSQL_TYPE_SET, so
we might need to modify the type to get the real type.
*/
enum_field_types source_type= static_cast<enum_field_types>(m_type[index]);
uint16 source_metadata= m_field_metadata[index];
switch (source_type)
{
case MYSQL_TYPE_STRING:
{
int real_type= source_metadata >> 8;
if (real_type == MYSQL_TYPE_ENUM || real_type == MYSQL_TYPE_SET)
source_type= static_cast<enum_field_types>(real_type);
break;
}
/*
This type has not been used since before row-based replication,
so we can safely assume that it really is MYSQL_TYPE_NEWDATE.
*/
case MYSQL_TYPE_DATE:
source_type= MYSQL_TYPE_NEWDATE;
break;
default:
/* Do nothing */
break;
}
return source_type;
}
......@@ -226,23 +160,58 @@ class table_def
with it.
A table definition is compatible with a table if:
- the columns types of the table definition is a (not
necessarily proper) prefix of the column type of the table, or
- the other way around
- The columns types of the table definition is a (not
necessarily proper) prefix of the column type of the table.
- The other way around.
- Each column on the master that also exists on the slave can be
converted according to the current settings of @c
SLAVE_TYPE_CONVERSIONS.
@param thd
@param rli Pointer to relay log info
@param table Pointer to table to compare with.
@param[out] tmp_table_var Pointer to temporary table for holding
conversion table.
@retval 1 if the table definition is not compatible with @c table
@retval 0 if the table definition is compatible with @c table
*/
#ifndef MYSQL_CLIENT
int compatible_with(Relay_log_info const *rli, TABLE *table) const;
bool compatible_with(THD *thd, Relay_log_info *rli, TABLE *table,
TABLE **conv_table_var) const;
/**
Create a virtual in-memory temporary table structure.
The table structure has records and field array so that a row can
be unpacked into the record for further processing.
In the virtual table, each field that requires conversion will
have a non-NULL value, while fields that do not require
conversion will have a NULL value.
Some information that is missing in the events, such as the
character set for string types, are taken from the table that the
field is going to be pushed into, so the target table that the data
eventually need to be pushed into need to be supplied.
@param thd Thread to allocate memory from.
@param rli Relay log info structure, for error reporting.
@param target_table Target table for fields.
@return A pointer to a temporary table with memory allocated in the
thread's memroot, NULL if the table could not be created
*/
TABLE *create_conversion_table(THD *thd, Relay_log_info *rli, TABLE *target_table) const;
#endif
private:
ulong m_size; // Number of elements in the types array
field_type *m_type; // Array of type descriptors
unsigned char *m_type; // Array of type descriptors
uint m_field_metadata_size;
uint16 *m_field_metadata;
uchar *m_null_bits;
......@@ -260,6 +229,7 @@ struct RPL_TABLE_LIST
{
bool m_tabledef_valid;
table_def m_tabledef;
TABLE *m_conv_table;
};
......
......@@ -92,6 +92,33 @@ TYPELIB delay_key_write_typelib=
delay_key_write_type_names, NULL
};
/**
SLAVE_TYPE_CONVERSIONS variable.
Definition is equivalent to
@code
SET('ALL_NON_LOSSY', 'ALL_LOSSY')
@endcode
*/
const char *slave_type_conversions_type_name[]= {
"ALL_LOSSY",
"ALL_NON_LOSSY",
NullS
};
unsigned int slave_type_conversions_type_length[]= {
sizeof("ALL_LOSSY")-1,
sizeof("ALL_NON_LOSSY")-1,
0
};
TYPELIB slave_type_conversions_typelib=
{
array_elements(slave_type_conversions_type_name)-1, "",
slave_type_conversions_type_name,
slave_type_conversions_type_length
};
const char *slave_exec_mode_names[]=
{ "STRICT", "IDEMPOTENT", NullS };
static const unsigned int slave_exec_mode_names_len[]=
......@@ -580,6 +607,12 @@ static sys_var_set_slave_mode slave_exec_mode(&vars,
&slave_exec_mode_options,
&slave_exec_mode_typelib,
0);
static sys_var_set slave_type_conversions(&vars,
"slave_type_conversions",
&slave_type_conversions_options,
&slave_type_conversions_typelib,
0);
static sys_var_long_ptr sys_slow_launch_time(&vars, "slow_launch_time",
&slow_launch_time);
static sys_var_thd_ulong sys_sort_buffer(&vars, "sort_buffer_size",
......@@ -1261,7 +1294,6 @@ bool sys_var_thd_binlog_format::check(THD *thd, set_var *var) {
return result;
}
bool sys_var_thd_binlog_format::is_readonly() const
{
/*
......
......@@ -32,6 +32,7 @@ typedef struct my_locale_st MY_LOCALE;
extern TYPELIB bool_typelib, delay_key_write_typelib, sql_mode_typelib,
optimizer_switch_typelib, slave_exec_mode_typelib;
extern TYPELIB slave_type_conversions_typelib;
typedef int (*sys_check_func)(THD *, set_var *);
typedef bool (*sys_update_func)(THD *, set_var *);
......
......@@ -6213,3 +6213,8 @@ ER_DEBUG_SYNC_TIMEOUT
ER_DEBUG_SYNC_HIT_LIMIT
eng "debug sync point hit limit reached"
ger "Debug Sync Point Hit Limit erreicht"
ER_SLAVE_CONVERSION_FAILED
eng "Column %d of table '%-.192s.%-.192s' cannot be converted from type '%-.32s' to type '%-.32s'"
ER_SLAVE_CANT_CREATE_CONVERSION
eng "Can't create conversion table for table '%-.192s.%-.192s'"
......@@ -86,6 +86,12 @@ enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON,
enum enum_slave_exec_mode { SLAVE_EXEC_MODE_STRICT,
SLAVE_EXEC_MODE_IDEMPOTENT,
SLAVE_EXEC_MODE_LAST_BIT};
enum enum_slave_type_conversions {
SLAVE_TYPE_CONVERSIONS_ALL_LOSSY,
SLAVE_TYPE_CONVERSIONS_ALL_NON_LOSSY,
SLAVE_TYPE_CONVERSIONS_COUNT
};
enum enum_mark_columns
{ MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE};
......
......@@ -10462,6 +10462,18 @@ TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list)
null_bit= 1;
}
}
if (cur_field->type() == MYSQL_TYPE_BIT &&
cur_field->key_type() == HA_KEYTYPE_BIT)
{
/* This is a Field_bit since key_type is HA_KEYTYPE_BIT */
static_cast<Field_bit*>(cur_field)->set_bit_ptr(null_pos, null_bit);
null_bit+= cur_field->field_length & 7;
if (null_bit > 7)
{
null_pos++;
null_bit-= 8;
}
}
cur_field->reset();
field_pos+= cur_field->pack_length();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment