summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2015-07-17 00:06:27 +0300
committerMonty <monty@mariadb.org>2015-07-17 00:06:27 +0300
commit00d3b20fbb669840daebf2a4483cead92221d78c (patch)
tree49e323d47483613cdbea769c74e8bf27d35f0fec
parentbc300464f1674dc774fd166a87d8894cbe498563 (diff)
downloadmariadb-git-00d3b20fbb669840daebf2a4483cead92221d78c.tar.gz
MDEV-8432 Slave cannot replicate signed integer-type values with high bit set to 1
The fix is that if the slave has a different integer size than the master, then they will assume the master has the same signed/unsigned modifier as the slave. This means that one can safely change a coon the slave an int to a bigint or an unsigned int to an unsigned int. Changing an unsigned int to an signed bigint will cause replication failures when the high bit of the unsigned int is set. We can't give an error if the signess is different on the master and slave as the binary log doesn't contain the signess of the column on the master.
-rw-r--r--mysql-test/suite/rpl/r/rpl_alter.result105
-rw-r--r--mysql-test/suite/rpl/t/rpl_alter.test53
-rw-r--r--sql/rpl_utility.cc21
3 files changed, 175 insertions, 4 deletions
diff --git a/mysql-test/suite/rpl/r/rpl_alter.result b/mysql-test/suite/rpl/r/rpl_alter.result
index 2cffa70d778..7be3bc576f3 100644
--- a/mysql-test/suite/rpl/r/rpl_alter.result
+++ b/mysql-test/suite/rpl/r/rpl_alter.result
@@ -14,4 +14,109 @@ select * from mysqltest.t3;
n
45
drop database mysqltest;
+use test;
+#
+# Test bug where ALTER TABLE MODIFY didn't replicate properly
+#
+create table t1 (a int unsigned primary key, b int);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(10) unsigned NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 (a) values (1),((1<<32)-1);
+select * from t1;
+a b
+1 NULL
+4294967295 NULL
+alter table t1 modify a bigint;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(20) NOT NULL DEFAULT '0',
+ `b` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t1;
+a b
+1 NULL
+4294967295 NULL
+alter table t1 modify a int unsigned;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(10) unsigned NOT NULL DEFAULT '0',
+ `b` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t1;
+a b
+1 NULL
+4294967295 NULL
+alter table t1 modify a bigint unsigned;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `b` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t1;
+a b
+1 NULL
+4294967295 NULL
+use test;
+select * from t1;
+a b
+1 NULL
+4294967295 NULL
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `b` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+create table t2 (a int unsigned auto_increment primary key, b int);
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `b` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t2 modify a bigint;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` bigint(20) NOT NULL DEFAULT '0',
+ `b` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t2 modify a bigint auto_increment;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` bigint(20) NOT NULL AUTO_INCREMENT,
+ `b` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1,t2;
+#
+# MDEV-8432: Slave cannot replicate signed integer-type values
+# with high bit set to 1
+# Test replication when we have int on master and bigint on slave
+#
+create table t1 (a int unsigned primary key, b int);
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_NON_LOSSY';
+alter table t1 modify a bigint unsigned;
+insert into t1 (a) values (1),((1<<32)-1);
+select * from t1;
+a b
+1 NULL
+4294967295 NULL
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='';
+drop table t1;
include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_alter.test b/mysql-test/suite/rpl/t/rpl_alter.test
index 630197f8637..8b8bcfb3d26 100644
--- a/mysql-test/suite/rpl/t/rpl_alter.test
+++ b/mysql-test/suite/rpl/t/rpl_alter.test
@@ -15,4 +15,57 @@ drop database mysqltest;
sync_slave_with_master;
# End of 4.1 tests
+
+connection master;
+use test;
+
+--echo #
+--echo # Test bug where ALTER TABLE MODIFY didn't replicate properly
+--echo #
+
+create table t1 (a int unsigned primary key, b int);
+show create table t1;
+insert into t1 (a) values (1),((1<<32)-1);
+select * from t1;
+alter table t1 modify a bigint;
+show create table t1;
+select * from t1;
+alter table t1 modify a int unsigned;
+show create table t1;
+select * from t1;
+alter table t1 modify a bigint unsigned;
+show create table t1;
+select * from t1;
+sync_slave_with_master;
+use test;
+select * from t1;
+show create table t1;
+connection master;
+#
+create table t2 (a int unsigned auto_increment primary key, b int);
+show create table t2;
+alter table t2 modify a bigint;
+show create table t2;
+alter table t2 modify a bigint auto_increment;
+show create table t2;
+drop table t1,t2;
+
+--echo #
+--echo # MDEV-8432: Slave cannot replicate signed integer-type values
+--echo # with high bit set to 1
+--echo # Test replication when we have int on master and bigint on slave
+--echo #
+
+create table t1 (a int unsigned primary key, b int);
+sync_slave_with_master;
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_NON_LOSSY';
+alter table t1 modify a bigint unsigned;
+connection master;
+insert into t1 (a) values (1),((1<<32)-1);
+sync_slave_with_master;
+select * from t1;
+SET GLOBAL SLAVE_TYPE_CONVERSIONS='';
+connection master;
+drop table t1;
+
--source include/rpl_end.inc
diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc
index e05ad5a8d43..9a20f71f4f7 100644
--- a/sql/rpl_utility.cc
+++ b/sql/rpl_utility.cc
@@ -876,6 +876,7 @@ TABLE *table_def::create_conversion_table(THD *thd, Relay_log_info *rli, TABLE *
{
Create_field *field_def=
(Create_field*) alloc_root(thd->mem_root, sizeof(Create_field));
+ bool unsigned_flag= 0;
if (field_list.push_back(field_def))
DBUG_RETURN(NULL);
@@ -885,8 +886,7 @@ TABLE *table_def::create_conversion_table(THD *thd, Relay_log_info *rli, TABLE *
uint32 max_length=
max_display_length_for_field(type(col), field_metadata(col));
- switch(type(col))
- {
+ switch(type(col)) {
int precision;
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
@@ -925,6 +925,18 @@ TABLE *table_def::create_conversion_table(THD *thd, Relay_log_info *rli, TABLE *
pack_length= field_metadata(col) & 0x00ff;
break;
+ case MYSQL_TYPE_TINY:
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_LONGLONG:
+ /*
+ As we don't know if the integer was signed or not on the master,
+ assume we have same sign on master and slave. This is true when not
+ using conversions so it should be true also when using conversions.
+ */
+ unsigned_flag= ((Field_num*) target_table->field[col])->unsigned_flag;
+ break;
default:
break;
}
@@ -932,12 +944,13 @@ TABLE *table_def::create_conversion_table(THD *thd, Relay_log_info *rli, TABLE *
DBUG_PRINT("debug", ("sql_type: %d, target_field: '%s', max_length: %d, decimals: %d,"
" maybe_null: %d, unsigned_flag: %d, pack_length: %u",
type(col), target_table->field[col]->field_name,
- max_length, decimals, TRUE, FALSE, pack_length));
+ max_length, decimals, TRUE, unsigned_flag,
+ pack_length));
field_def->init_for_tmp_table(type(col),
max_length,
decimals,
TRUE, // maybe_null
- FALSE, // unsigned_flag
+ unsigned_flag,
pack_length);
field_def->charset= target_table->field[col]->charset();
field_def->interval= interval;