diff --git a/mysql-test/std_data/temporal_upgrade/mysql050614_temporal0.MYD b/mysql-test/std_data/temporal_upgrade/mysql050614_temporal0.MYD new file mode 100644 index 00000000000..c04784cf1d4 Binary files /dev/null and b/mysql-test/std_data/temporal_upgrade/mysql050614_temporal0.MYD differ diff --git a/mysql-test/std_data/temporal_upgrade/mysql050614_temporal0.MYI b/mysql-test/std_data/temporal_upgrade/mysql050614_temporal0.MYI new file mode 100644 index 00000000000..9b5533c01a7 Binary files /dev/null and b/mysql-test/std_data/temporal_upgrade/mysql050614_temporal0.MYI differ diff --git a/mysql-test/std_data/temporal_upgrade/mysql050614_temporal0.frm b/mysql-test/std_data/temporal_upgrade/mysql050614_temporal0.frm new file mode 100644 index 00000000000..890ca106e28 Binary files /dev/null and b/mysql-test/std_data/temporal_upgrade/mysql050614_temporal0.frm differ diff --git a/mysql-test/std_data/temporal_upgrade/mysql050614_temporal1.MYD b/mysql-test/std_data/temporal_upgrade/mysql050614_temporal1.MYD new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mysql-test/std_data/temporal_upgrade/mysql050614_temporal1.MYI b/mysql-test/std_data/temporal_upgrade/mysql050614_temporal1.MYI new file mode 100644 index 00000000000..2b1538988be Binary files /dev/null and b/mysql-test/std_data/temporal_upgrade/mysql050614_temporal1.MYI differ diff --git a/mysql-test/std_data/temporal_upgrade/mysql050614_temporal1.frm b/mysql-test/std_data/temporal_upgrade/mysql050614_temporal1.frm new file mode 100644 index 00000000000..6b9af25392d Binary files /dev/null and b/mysql-test/std_data/temporal_upgrade/mysql050614_temporal1.frm differ diff --git a/mysql-test/suite/rpl/r/rpl_temporal_mysql56_to_mariadb.result b/mysql-test/suite/rpl/r/rpl_temporal_mysql56_to_mariadb.result new file mode 100644 index 00000000000..ecc95481f2d --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_temporal_mysql56_to_mariadb.result @@ -0,0 +1,36 @@ +include/master-slave.inc +[connection master] +# +# Testing replication from MariaDB-10.0 master +# started over MySQL-5.6 data directory +# to MariaDB-10.0 slave running with natively created tables +# +SET TIME_ZONE='+00:00'; +SHOW CREATE TABLE mysql050614_temporal0; +Table Create Table +mysql050614_temporal0 CREATE TABLE `mysql050614_temporal0` ( + `a` time DEFAULT NULL, + `b` datetime DEFAULT NULL, + `c` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SHOW CREATE TABLE mysql050614_temporal1; +Table Create Table +mysql050614_temporal1 CREATE TABLE `mysql050614_temporal1` ( + `a` time(1) DEFAULT NULL, + `b` datetime(1) DEFAULT NULL, + `c` timestamp(1) NOT NULL DEFAULT CURRENT_TIMESTAMP(1) ON UPDATE CURRENT_TIMESTAMP(1) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SET TIME_ZONE='+00:00'; +CREATE TABLE mysql050614_temporal0 (a time(0), b datetime(0), c timestamp(0)) engine=myisam; +CREATE TABLE mysql050614_temporal1 (a time(1), b datetime(1), c timestamp(1)) engine=myisam; +INSERT INTO mysql050614_temporal0 VALUES ('00:00:02','2001-01-01 00:00:02','2001-01-01 00:00:02'); +INSERT INTO mysql050614_temporal1 VALUES ('00:00:02.1','2001-01-01 00:00:02.2','2001-01-01 00:00:02.3'); +SELECT * FROM mysql050614_temporal0; +a b c +00:00:02 2001-01-01 00:00:02 2001-01-01 00:00:02 +SELECT * FROM mysql050614_temporal1; +a b c +00:00:02.1 2001-01-01 00:00:02.2 2001-01-01 00:00:02.3 +DROP TABLE mysql050614_temporal0; +DROP TABLE mysql050614_temporal1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb.test b/mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb.test new file mode 100644 index 00000000000..46c51a5e465 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb.test @@ -0,0 +1,42 @@ +--source include/master-slave.inc + + +--echo # +--echo # Testing replication from MariaDB-10.0 master +--echo # started over MySQL-5.6 data directory +--echo # to MariaDB-10.0 slave running with natively created tables +--echo # + +connection master; +SET TIME_ZONE='+00:00'; +let $MYSQLD_MASTER_DATADIR= `select @@datadir`; + +--copy_file std_data/temporal_upgrade/mysql050614_temporal0.frm $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal0.frm +--copy_file std_data/temporal_upgrade/mysql050614_temporal0.MYD $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal0.MYD +--copy_file std_data/temporal_upgrade/mysql050614_temporal0.MYI $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal0.MYI + +--copy_file std_data/temporal_upgrade/mysql050614_temporal1.frm $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal1.frm +--copy_file std_data/temporal_upgrade/mysql050614_temporal1.MYD $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal1.MYD +--copy_file std_data/temporal_upgrade/mysql050614_temporal1.MYI $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal1.MYI +SHOW CREATE TABLE mysql050614_temporal0; +SHOW CREATE TABLE mysql050614_temporal1; + +connection slave; +SET TIME_ZONE='+00:00'; +CREATE TABLE mysql050614_temporal0 (a time(0), b datetime(0), c timestamp(0)) engine=myisam; +CREATE TABLE mysql050614_temporal1 (a time(1), b datetime(1), c timestamp(1)) engine=myisam; + +connection master; +INSERT INTO mysql050614_temporal0 VALUES ('00:00:02','2001-01-01 00:00:02','2001-01-01 00:00:02'); +INSERT INTO mysql050614_temporal1 VALUES ('00:00:02.1','2001-01-01 00:00:02.2','2001-01-01 00:00:02.3'); +sync_slave_with_master; + +connection slave; +SELECT * FROM mysql050614_temporal0; +SELECT * FROM mysql050614_temporal1; + +connection master; +DROP TABLE mysql050614_temporal0; +DROP TABLE mysql050614_temporal1; + +--source include/rpl_end.inc diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index 590a5ae06ac..1f67dd6ee8f 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -46,6 +46,19 @@ uint32 uint_max(int bits) { } +/** + Calculate display length for MySQL56 temporal data types from their metadata. + It contains fractional precision in the low 16-bit word. +*/ +static uint32 +max_display_length_for_temporal2_field(uint32 int_display_length, + unsigned int metadata) +{ + metadata&= 0x00ff; + return int_display_length + metadata + (metadata ? 1 : 0); +} + + /** Compute the maximum display length of a field. @@ -109,17 +122,23 @@ max_display_length_for_field(enum_field_types sql_type, unsigned int metadata) case MYSQL_TYPE_DATE: case MYSQL_TYPE_TIME: - case MYSQL_TYPE_TIME2: return 3; + case MYSQL_TYPE_TIME2: + return max_display_length_for_temporal2_field(MIN_TIME_WIDTH, metadata); + case MYSQL_TYPE_TIMESTAMP: - case MYSQL_TYPE_TIMESTAMP2: return 4; + case MYSQL_TYPE_TIMESTAMP2: + return max_display_length_for_temporal2_field(MAX_DATETIME_WIDTH, metadata); + case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_DATETIME2: return 8; + case MYSQL_TYPE_DATETIME2: + return max_display_length_for_temporal2_field(MAX_DATETIME_WIDTH, metadata); + case MYSQL_TYPE_BIT: /* Decode the size of the bit field from the master. @@ -630,19 +649,32 @@ can_convert_field_to(Field *field, else DBUG_RETURN(false); } - else if (metadata == 0 && - ((field->real_type() == MYSQL_TYPE_TIMESTAMP2 && - source_type == MYSQL_TYPE_TIMESTAMP) || - (field->real_type() == MYSQL_TYPE_TIME2 && - source_type == MYSQL_TYPE_TIME) || - (field->real_type() == MYSQL_TYPE_DATETIME2 && - source_type == MYSQL_TYPE_DATETIME))) + else if ( + /* + Conversion from MariaDB TIMESTAMP(0), TIME(0), DATETIME(0) + to the corresponding MySQL56 types is non-lossy. + */ + (metadata == 0 && + ((field->real_type() == MYSQL_TYPE_TIMESTAMP2 && + source_type == MYSQL_TYPE_TIMESTAMP) || + (field->real_type() == MYSQL_TYPE_TIME2 && + source_type == MYSQL_TYPE_TIME) || + (field->real_type() == MYSQL_TYPE_DATETIME2 && + source_type == MYSQL_TYPE_DATETIME))) || + /* + Conversion from MySQL56 TIMESTAMP(N), TIME(N), DATETIME(N) + to the corresponding MariaDB or MySQL55 types is non-lossy. + */ + (metadata == field->decimals() && + ((field->real_type() == MYSQL_TYPE_TIMESTAMP && + source_type == MYSQL_TYPE_TIMESTAMP2) || + (field->real_type() == MYSQL_TYPE_TIME && + source_type == MYSQL_TYPE_TIME2) || + (field->real_type() == MYSQL_TYPE_DATETIME && + source_type == MYSQL_TYPE_DATETIME2)))) { /* TS-TODO: conversion from FSP1>FSP2. - Can do non-lossy conversion - from old TIME, TIMESTAMP, DATETIME - to MySQL56 TIME(0), TIMESTAMP(0), DATETIME(0). */ *order_var= -1; DBUG_RETURN(true);