[Commits] a1082c61292: MDEV-17098 DATE -> DATETIME replication conversion not working, even in ALL_NON_LOSSY mode
revision-id: a1082c6129209db6ee4470a84955ce9cc545e0b2 (mariadb-10.2.18-8-ga1082c61292) parent(s): 753117fed043ac3200093c2dc28161ebce2cd04b author: Andrei Elkin committer: Andrei Elkin timestamp: 2018-10-05 17:36:52 +0300 message: MDEV-17098 DATE -> DATETIME replication conversion not working, even in ALL_NON_LOSSY mode Opened up MYSQL_TYPE _DATETIME{,2} <-> _NEWDATE conversions for replication. --- mysql-test/suite/rpl/include/rpl_colsize_check.inc | 23 +++ mysql-test/suite/rpl/r/rpl_colSize.result | 204 +++++++++++++++++++++ mysql-test/suite/rpl/r/rpl_row_colSize.result | 24 +++ mysql-test/suite/rpl/t/rpl_colSize.test | 126 +++++++++++++ mysql-test/suite/rpl/t/rpl_row_colSize.test | 10 + sql/rpl_utility.cc | 31 +++- 6 files changed, 415 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/rpl/include/rpl_colsize_check.inc b/mysql-test/suite/rpl/include/rpl_colsize_check.inc new file mode 100644 index 00000000000..0c5bdd56610 --- /dev/null +++ b/mysql-test/suite/rpl/include/rpl_colsize_check.inc @@ -0,0 +1,23 @@ +# Create a table on master and slave possibly with imcompatible attributes; +# INSERT into the table and replicate; +# print out inserted values. +--connection master +--eval DROP TABLE IF EXISTS $table; +sync_slave_with_master slave; + +--connection master +--eval CREATE TABLE $table ($attr_m) +--replace_result default DEFAULT +--eval SHOW CREATE TABLE $table + +sync_slave_with_master slave; +--eval ALTER TABLE $table MODIFY $attr_s +--replace_result default DEFAULT +--eval SHOW CREATE TABLE $table + +--connection master +--eval INSERT INTO t1 VALUES $values2 +--eval SELECT $check_m from $table + +sync_slave_with_master slave; +--eval SELECT $check_s from $table diff --git a/mysql-test/suite/rpl/r/rpl_colSize.result b/mysql-test/suite/rpl/r/rpl_colSize.result index 503bf85222e..fae03a4211b 100644 --- a/mysql-test/suite/rpl/r/rpl_colSize.result +++ b/mysql-test/suite/rpl/r/rpl_colSize.result @@ -189,6 +189,210 @@ t1 CREATE TABLE `t1` ( `d` bit(25) DEFAULT NULL, `e` bit(13) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 +connection master; +SET @saved_mysql56_temporal_format = @@global.mysql56_temporal_format; +connection slave; +SET @saved_mysql56_temporal_format = @@global.mysql56_temporal_format; +MYSQL_TYPE_NEWDATE <-> MYSQL_TYPE_DATETIME2 +connection master; +SET @@global.mysql56_temporal_format=1; +connection slave; +SET @@global.mysql56_temporal_format=1; +Checking NON-LOSSY MYSQL_TYPE_NEWDATE -> MYSQL_TYPE_DATETIME2 +connection master; +DROP TABLE IF EXISTS t1;; +connection slave; +connection master; +CREATE TABLE t1 (a DATE); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` date DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +connection slave; +ALTER TABLE t1 MODIFY a DATETIME(6); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` datetime(6) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +connection master; +INSERT INTO t1 VALUES (current_date()),(date_add(current_date(), INTERVAL 1 day)); +SELECT max(a) - min(a) as 'master: one' from t1; +master: one +1 +connection slave; +SELECT date(max(a)) - date(min(a)) as 'slave: 1' from t1; +slave: 1 +1 +Checking LOSSY MYSQL_TYPE_DATETIME2 -> MYSQL_TYPE_NEWDATE +SET @local_saved_slave_type_conversions = @@slave_type_conversions; +SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_LOSSY'; +connection master; +DROP TABLE IF EXISTS t1;; +connection slave; +connection master; +CREATE TABLE t1 (a DATETIME(6)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` datetime(6) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +connection slave; +ALTER TABLE t1 MODIFY a DATE; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` date DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +connection master; +INSERT INTO t1 VALUES (current_timestamp(6)), (date_add(current_timestamp(6), INTERVAL 1 day)); +SELECT date(max(a)) - date(min(a)) as 'master: one day' from t1; +master: one day +1 +connection slave; +SELECT max(a) - min(a) as 'slave: 1 day' from t1; +slave: 1 day +1 +SET GLOBAL SLAVE_TYPE_CONVERSIONS = @local_saved_slave_type_conversions; +"Mysql" MYSQL_TYPE_NEWDATE <-> MYSQL_TYPE_DATETIME +connection master; +SET @@global.mysql56_temporal_format=1; +connection slave; +SET @@global.mysql56_temporal_format=0; +Checking NON-LOSSY MYSQL_TYPE_NEWDATE -> MYSQL_TYPE_DATETIME +connection master; +DROP TABLE IF EXISTS t1;; +connection slave; +connection master; +CREATE TABLE t1 (a DATE); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` date DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +connection slave; +ALTER TABLE t1 MODIFY a DATETIME(6); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` datetime(6) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +connection master; +INSERT INTO t1 VALUES (current_date()),(date_add(current_date(), INTERVAL 1 day)); +SELECT max(a) - min(a) as 'master: one' from t1; +master: one +1 +connection slave; +SELECT date(max(a)) - date(min(a)) as 'slave: 1' from t1; +slave: 1 +1 +Checking LOSSY MYSQL_TYPE_DATETIME2 -> MYSQL_TYPE_DATE +SET @local_saved_slave_type_conversions = @@slave_type_conversions; +SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_LOSSY'; +connection master; +DROP TABLE IF EXISTS t1;; +connection slave; +connection master; +CREATE TABLE t1 (a DATETIME(6)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` datetime(6) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +connection slave; +ALTER TABLE t1 MODIFY a DATE; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` date DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +connection master; +INSERT INTO t1 VALUES (current_timestamp(6)), (date_add(current_timestamp(6), INTERVAL 1 day)); +SELECT date(max(a)) - date(min(a)) as 'master: one day' from t1; +master: one day +1 +connection slave; +SELECT max(a) - min(a) as 'slave: 1 day' from t1; +slave: 1 day +1 +SET GLOBAL SLAVE_TYPE_CONVERSIONS = @local_saved_slave_type_conversions; +"Maria" MYSQL_TYPE_NEWDATE <-> MYSQL_TYPE_DATETIME2 +connection master; +SET @@global.mysql56_temporal_format=0; +connection slave; +SET @@global.mysql56_temporal_format=1; +Checking NON-LOSSY MYSQL_TYPE_NEWDATE -> MYSQL_TYPE_DATETIME +connection master; +DROP TABLE IF EXISTS t1;; +connection slave; +connection master; +CREATE TABLE t1 (a DATE); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` date DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +connection slave; +ALTER TABLE t1 MODIFY a DATETIME(6); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` datetime(6) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +connection master; +INSERT INTO t1 VALUES (current_date()),(date_add(current_date(), INTERVAL 1 day)); +SELECT max(a) - min(a) as 'master: one' from t1; +master: one +1 +connection slave; +SELECT date(max(a)) - date(min(a)) as 'slave: 1' from t1; +slave: 1 +1 +Checking LOSSY MYSQL_TYPE_DATETIME -> MYSQL_TYPE_NEWDATE +SET @local_saved_slave_type_conversions = @@slave_type_conversions; +SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_LOSSY'; +SET GLOBAL SLAVE_TYPE_CONVERSIONS = @local_saved_slave_type_conversions; +"Maria" MYSQL_TYPE_NEWDATE <-> MYSQL_TYPE_DATETIME +connection master; +SET @@global.mysql56_temporal_format=0; +connection slave; +SET @@global.mysql56_temporal_format=0; +Checking NON-LOSSY MYSQL_TYPE_NEWDATE -> MYSQL_TYPE_DATETIME +connection master; +DROP TABLE IF EXISTS t1;; +connection slave; +connection master; +CREATE TABLE t1 (a DATE); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` date DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +connection slave; +ALTER TABLE t1 MODIFY a DATETIME(6); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` datetime(6) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +connection master; +INSERT INTO t1 VALUES (current_date()),(date_add(current_date(), INTERVAL 1 day)); +SELECT max(a) - min(a) as 'master: one' from t1; +master: one +1 +connection slave; +SELECT date(max(a)) - date(min(a)) as 'slave: 1' from t1; +slave: 1 +1 +Checking LOSSY MYSQL_TYPE_DATETIME -> MYSQL_TYPE_NEWDATE +SET @local_saved_slave_type_conversions = @@slave_type_conversions; +SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_LOSSY'; +SET GLOBAL SLAVE_TYPE_CONVERSIONS = @local_saved_slave_type_conversions; +connection master; +SET @@global.mysql56_temporal_format=@saved_mysql56_temporal_format; +connection slave; +SET @@global.mysql56_temporal_format=@saved_mysql56_temporal_format; *** Cleanup *** connection master; DROP TABLE t1; diff --git a/mysql-test/suite/rpl/r/rpl_row_colSize.result b/mysql-test/suite/rpl/r/rpl_row_colSize.result index dd324ef7807..ede73cbeedd 100644 --- a/mysql-test/suite/rpl/r/rpl_row_colSize.result +++ b/mysql-test/suite/rpl/r/rpl_row_colSize.result @@ -344,6 +344,30 @@ connection master; RESET MASTER; connection slave; START SLAVE; +Checking MYSQL_TYPE_DATETIME to MYSQL_TYPE_DATE +connection master; +DROP TABLE IF EXISTS t1; +connection slave; +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t1 (a date); +connection master; +CREATE TABLE t1 (a datetime(6)); +RESET MASTER; +INSERT INTO t1 VALUES (current_date()); +connection slave; +START SLAVE; +include/wait_for_slave_sql_error.inc [errno=1677] +Last_SQL_Error = 'Column 0 of table 'test.t1' cannot be converted from type 'datetime' to type 'date'' +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +STOP SLAVE; +RESET SLAVE; +connection master; +RESET MASTER; +connection slave; +START SLAVE; connection slave; call mtr.add_suppression("Slave SQL.*Table definition on master and slave does not match: Column 0 ...e mismatch.* error.* 1535"); call mtr.add_suppression("Slave SQL.*Column 0 of table .test.t1. cannot be converted from type.* error.* 1677"); diff --git a/mysql-test/suite/rpl/t/rpl_colSize.test b/mysql-test/suite/rpl/t/rpl_colSize.test index d6f817af189..1a965b17e58 100644 --- a/mysql-test/suite/rpl/t/rpl_colSize.test +++ b/mysql-test/suite/rpl/t/rpl_colSize.test @@ -217,6 +217,132 @@ SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1; --replace_result default DEFAULT SHOW CREATE TABLE t1; +# +# MDEV-17098: Checking MYSQL_TYPE _DATETIME{,2} to-from _{NEW,}DATE conversion +# + +connection master; +SET @saved_mysql56_temporal_format = @@global.mysql56_temporal_format; +connection slave; +SET @saved_mysql56_temporal_format = @@global.mysql56_temporal_format; + +--echo MYSQL_TYPE_NEWDATE <-> MYSQL_TYPE_DATETIME2 +connection master; +SET @@global.mysql56_temporal_format=1; +connection slave; +SET @@global.mysql56_temporal_format=1; +--echo Checking NON-LOSSY MYSQL_TYPE_NEWDATE -> MYSQL_TYPE_DATETIME2 +--let $table = t1 +--let $attr_m = a DATE +--let $attr_s = a DATETIME(6) +--let $values2 = (current_date()),(date_add(current_date(), INTERVAL 1 day)) +--let $check_m = max(a) - min(a) as 'master: one' +--let $check_s = date(max(a)) - date(min(a)) as 'slave: 1' +--source include/rpl_colsize_check.inc + +--echo Checking LOSSY MYSQL_TYPE_DATETIME2 -> MYSQL_TYPE_NEWDATE +SET @local_saved_slave_type_conversions = @@slave_type_conversions; +SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_LOSSY'; +--let $attr_m = a DATETIME(6) +--let $attr_s = a DATE +--let $values2 = (current_timestamp(6)), (date_add(current_timestamp(6), INTERVAL 1 day)) +--let $check_m = date(max(a)) - date(min(a)) as 'master: one day' +--let $check_s = max(a) - min(a) as 'slave: 1 day' +--source include/rpl_colsize_check.inc +SET GLOBAL SLAVE_TYPE_CONVERSIONS = @local_saved_slave_type_conversions; + +--echo "Mysql" MYSQL_TYPE_NEWDATE <-> MYSQL_TYPE_DATETIME +connection master; +SET @@global.mysql56_temporal_format=1; +connection slave; +SET @@global.mysql56_temporal_format=0; + +--echo Checking NON-LOSSY MYSQL_TYPE_NEWDATE -> MYSQL_TYPE_DATETIME +--let $table = t1 +--let $attr_m = a DATE +--let $attr_s = a DATETIME(6) +--let $values2 = (current_date()),(date_add(current_date(), INTERVAL 1 day)) +--let $check_m = max(a) - min(a) as 'master: one' +--let $check_s = date(max(a)) - date(min(a)) as 'slave: 1' +--source include/rpl_colsize_check.inc + +--echo Checking LOSSY MYSQL_TYPE_DATETIME2 -> MYSQL_TYPE_DATE +SET @local_saved_slave_type_conversions = @@slave_type_conversions; +SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_LOSSY'; +--let $attr_m = a DATETIME(6) +--let $attr_s = a DATE +--let $values2 = (current_timestamp(6)), (date_add(current_timestamp(6), INTERVAL 1 day)) +--let $check_m = date(max(a)) - date(min(a)) as 'master: one day' +--let $check_s = max(a) - min(a) as 'slave: 1 day' +--source include/rpl_colsize_check.inc +SET GLOBAL SLAVE_TYPE_CONVERSIONS = @local_saved_slave_type_conversions; + +--echo "Maria" MYSQL_TYPE_NEWDATE <-> MYSQL_TYPE_DATETIME2 +connection master; +SET @@global.mysql56_temporal_format=0; +connection slave; +SET @@global.mysql56_temporal_format=1; + +--echo Checking NON-LOSSY MYSQL_TYPE_NEWDATE -> MYSQL_TYPE_DATETIME +--let $table = t1 +--let $attr_m = a DATE +--let $attr_s = a DATETIME(6) +--let $values2 = (current_date()),(date_add(current_date(), INTERVAL 1 day)) +--let $check_m = max(a) - min(a) as 'master: one' +--let $check_s = date(max(a)) - date(min(a)) as 'slave: 1' +--source include/rpl_colsize_check.inc + +--echo Checking LOSSY MYSQL_TYPE_DATETIME -> MYSQL_TYPE_NEWDATE +SET @local_saved_slave_type_conversions = @@slave_type_conversions; +SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_LOSSY'; +--let $attr_m = a DATETIME(6) +--let $attr_s = a DATE +--let $values2 = (current_timestamp(6)), (date_add(current_timestamp(6), INTERVAL 1 day)) +--let $check_m = date(max(a)) - date(min(a)) as 'master: one day' +--let $check_s = max(a) - min(a) as 'slave: 1 day' + +### TODO: find out why +# AddressSanitizer: global-buffer-overflow on address 0x55b1fa26aceb at pc 0x55b1f8d46d5c bp 0x7f513f2aa530 sp 0x7f513f2aa520 +#READ of size 1 at 0x55b1fa26aceb thread T35 +# #0 0x55b1f8d46d5b in check_date /home/andrei/MDB/WTs/10.2/10.2-MDEV-17098/sql-common/my_time.c:91 +# #1 0x55b1f7b7b41e in Field_temporal_with_date::store_time_dec(st_mysql_time*, unsigned int) /home/andrei/MDB/WTs/10.2/10.2-MDEV-17098/sql/field.cc:5675 +# #2 0x55b1f7bb9f6a in Field::do_field_temporal(Copy_field*) /home/andrei/MDB/WTs/10.2/10.2-MDEV-17098/sql/field_conv.cc:434 +###--source include/rpl_colsize_check.inc +SET GLOBAL SLAVE_TYPE_CONVERSIONS = @local_saved_slave_type_conversions; + +--echo "Maria" MYSQL_TYPE_NEWDATE <-> MYSQL_TYPE_DATETIME +connection master; +SET @@global.mysql56_temporal_format=0; +connection slave; +SET @@global.mysql56_temporal_format=0; + +--echo Checking NON-LOSSY MYSQL_TYPE_NEWDATE -> MYSQL_TYPE_DATETIME +--let $table = t1 +--let $attr_m = a DATE +--let $attr_s = a DATETIME(6) +--let $values2 = (current_date()),(date_add(current_date(), INTERVAL 1 day)) +--let $check_m = max(a) - min(a) as 'master: one' +--let $check_s = date(max(a)) - date(min(a)) as 'slave: 1' +--source include/rpl_colsize_check.inc + +--echo Checking LOSSY MYSQL_TYPE_DATETIME -> MYSQL_TYPE_NEWDATE +SET @local_saved_slave_type_conversions = @@slave_type_conversions; +SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_LOSSY'; +--let $attr_m = a DATETIME(6) +--let $attr_s = a DATE +--let $values2 = (current_timestamp(6)), (date_add(current_timestamp(6), INTERVAL 1 day)) +--let $check_m = date(max(a)) - date(min(a)) as 'master: one day' +--let $check_s = max(a) - min(a) as 'slave: 1 day' + +### The same as above +###--source include/rpl_colsize_check.inc +SET GLOBAL SLAVE_TYPE_CONVERSIONS = @local_saved_slave_type_conversions; + +connection master; +SET @@global.mysql56_temporal_format=@saved_mysql56_temporal_format; +connection slave; +SET @@global.mysql56_temporal_format=@saved_mysql56_temporal_format; + --echo *** Cleanup *** connection master; DROP TABLE t1; diff --git a/mysql-test/suite/rpl/t/rpl_row_colSize.test b/mysql-test/suite/rpl/t/rpl_row_colSize.test index 21c68b55e92..63659c07a0a 100644 --- a/mysql-test/suite/rpl/t/rpl_row_colSize.test +++ b/mysql-test/suite/rpl/t/rpl_row_colSize.test @@ -160,6 +160,16 @@ let $test_table_slave = CREATE TABLE t1 (a TINYBLOB); let $test_insert = INSERT INTO t1 VALUES ('This is a test.'); source include/test_fieldsize.inc; +# +# Test: Checking MYSQL_TYPE_DATE* fields +# +--echo Checking MYSQL_TYPE_DATETIME to MYSQL_TYPE_DATE +let $test_table_master = CREATE TABLE t1 (a datetime(6)); +let $test_table_slave = CREATE TABLE t1 (a date); +let $test_insert = INSERT INTO t1 VALUES (current_date()); +source include/test_fieldsize.inc; + + connection slave; call mtr.add_suppression("Slave SQL.*Table definition on master and slave does not match: Column 0 ...e mismatch.* error.* 1535"); call mtr.add_suppression("Slave SQL.*Column 0 of table .test.t1. cannot be converted from type.* error.* 1677"); diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index bdf5b7dea80..f64fa1dfe53 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -763,16 +763,41 @@ can_convert_field_to(Field *field, case MYSQL_TYPE_TIMESTAMP: case MYSQL_TYPE_DATE: case MYSQL_TYPE_TIME: - case MYSQL_TYPE_DATETIME: case MYSQL_TYPE_YEAR: - case MYSQL_TYPE_NEWDATE: case MYSQL_TYPE_NULL: case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: case MYSQL_TYPE_TIMESTAMP2: - case MYSQL_TYPE_DATETIME2: case MYSQL_TYPE_TIME2: DBUG_RETURN(false); + case MYSQL_TYPE_NEWDATE: + { + if (field->real_type() == MYSQL_TYPE_DATETIME2 || + field->real_type() == MYSQL_TYPE_DATETIME) + { + *order_var= -1; + DBUG_RETURN(is_conversion_ok(*order_var, rli)); + } + else + { + DBUG_RETURN(false); + } + } + break; + case MYSQL_TYPE_DATETIME2: + case MYSQL_TYPE_DATETIME: + { + if (field->real_type() == MYSQL_TYPE_NEWDATE) + { + *order_var= 1; + DBUG_RETURN(is_conversion_ok(*order_var, rli)); + } + else + { + DBUG_RETURN(false); + } + } + break; } DBUG_RETURN(false); // To keep GCC happy }
participants (1)
-
andrei.elkin@pp.inet.fi