diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-11-13 22:58:19 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-11-13 22:58:19 +0100 |
commit | c155890af90ec75555fa485387a0cf11120175a6 (patch) | |
tree | 5b06186dc99f9dd83a5aac2c98c9d73eed5c7742 | |
parent | 80137baf2fe262607e91e7a518789f12ad815819 (diff) | |
download | mariadb-git-c155890af90ec75555fa485387a0cf11120175a6.tar.gz |
MDEV-5248 Serious incompatibility and data corruption of DATETIME and DATE types due to get_innobase_type_from_mysql_type refactor combined with InnoDB Online DDL
restore old innodb get_innobase_type_from_mysql_type() function,
record all mysql_type->innodb_type mapping
(as generated by mysql-5.6).
add safety code to disable online alter when internal types don't match
storage/innobase/dict/dict0stats.cc:
revert to 5.6 state
-rw-r--r-- | mysql-test/suite/innodb/r/1byte_data_int.result | 23 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/data_types.result | 155 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/1byte_data_int.test | 25 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/data_types.opt (renamed from mysql-test/suite/innodb/t/1byte_data_int.opt) | 0 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/data_types.test | 118 | ||||
-rw-r--r-- | storage/innobase/dict/dict0stats.cc | 4 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 121 | ||||
-rw-r--r-- | storage/innobase/handler/handler0alter.cc | 26 |
8 files changed, 374 insertions, 98 deletions
diff --git a/mysql-test/suite/innodb/r/1byte_data_int.result b/mysql-test/suite/innodb/r/1byte_data_int.result deleted file mode 100644 index 28cb85afcd8..00000000000 --- a/mysql-test/suite/innodb/r/1byte_data_int.result +++ /dev/null @@ -1,23 +0,0 @@ -# Create a table with a 1-byte ENUM, 1-byte SET, and TINYINT UNSIGNED. -CREATE TABLE t1 -( -t1_enum ENUM("a", "b", "c"), -t1_set SET("a", "b", "c"), -t1_tinyint_s TINYINT, -t1_tinyint_u TINYINT UNSIGNED -) ENGINE=InnoDB; -# All t1 fields' mtypes should be 6 (DATA_INT). -SELECT -name, -mtype, -(prtype & 512) = 512 AS is_unsigned -FROM information_schema.INNODB_SYS_COLUMNS -WHERE name LIKE "t1\_%" -ORDER BY name; -name mtype is_unsigned -t1_enum 6 1 -t1_set 6 1 -t1_tinyint_s 6 0 -t1_tinyint_u 6 1 -# Cleanup -DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/data_types.result b/mysql-test/suite/innodb/r/data_types.result new file mode 100644 index 00000000000..c026d44eb79 --- /dev/null +++ b/mysql-test/suite/innodb/r/data_types.result @@ -0,0 +1,155 @@ +CREATE TABLE t1 +( +t1_BIGINT BIGINT, +t1_BIGINT_UNSIGNED BIGINT UNSIGNED, +t1_BINARY_100 BINARY(100), +t1_BIT_2 BIT(2), +t1_BIT_20 BIT(20), +t1_BLOB BLOB, +t1_CHAR_100 CHAR(100), +t1_CHAR_100_BINARY CHAR(100) BINARY, +t1_DATE DATE, +t1_DATETIME DATETIME, +t1_DATETIME_6 DATETIME(6), +t1_DECIMAL_10_3 DECIMAL(10,3), +t1_DECIMAL_10_3_UNSIGNED DECIMAL(10,3) UNSIGNED, +t1_DOUBLE DOUBLE, +t1_DOUBLE_UNSIGNED DOUBLE UNSIGNED, +t1_ENUM ENUM('a', 'b', 'c'), +t1_ENUM_BINARY ENUM('a','b') BINARY, +t1_ENUM_256 ENUM('a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', +'a10', 'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a17', 'a18', 'a19', +'a20', 'a21', 'a22', 'a23', 'a24', 'a25', 'a26', 'a27', 'a28', 'a29', +'a30', 'a31', 'a32', 'a33', 'a34', 'a35', 'a36', 'a37', 'a38', 'a39', +'a40', 'a41', 'a42', 'a43', 'a44', 'a45', 'a46', 'a47', 'a48', 'a49', +'a50', 'a51', 'a52', 'a53', 'a54', 'a55', 'a56', 'a57', 'a58', 'a59', +'a60', 'a61', 'a62', 'a63', 'a64', 'a65', 'a66', 'a67', 'a68', 'a69', +'a70', 'a71', 'a72', 'a73', 'a74', 'a75', 'a76', 'a77', 'a78', 'a79', +'a80', 'a81', 'a82', 'a83', 'a84', 'a85', 'a86', 'a87', 'a88', 'a89', +'a90', 'a91', 'a92', 'a93', 'a94', 'a95', 'a96', 'a97', 'a98', 'a99', +'a100', 'a101', 'a102', 'a103', 'a104', 'a105', 'a106', 'a107', 'a108', +'a109', 'a110', 'a111', 'a112', 'a113', 'a114', 'a115', 'a116', 'a117', +'a118', 'a119', 'a120', 'a121', 'a122', 'a123', 'a124', 'a125', 'a126', +'a127', 'a128', 'a129', 'a130', 'a131', 'a132', 'a133', 'a134', 'a135', +'a136', 'a137', 'a138', 'a139', 'a140', 'a141', 'a142', 'a143', 'a144', +'a145', 'a146', 'a147', 'a148', 'a149', 'a150', 'a151', 'a152', 'a153', +'a154', 'a155', 'a156', 'a157', 'a158', 'a159', 'a160', 'a161', 'a162', +'a163', 'a164', 'a165', 'a166', 'a167', 'a168', 'a169', 'a170', 'a171', +'a172', 'a173', 'a174', 'a175', 'a176', 'a177', 'a178', 'a179', 'a180', +'a181', 'a182', 'a183', 'a184', 'a185', 'a186', 'a187', 'a188', 'a189', +'a190', 'a191', 'a192', 'a193', 'a194', 'a195', 'a196', 'a197', 'a198', +'a199', 'a200', 'a201', 'a202', 'a203', 'a204', 'a205', 'a206', 'a207', +'a208', 'a209', 'a210', 'a211', 'a212', 'a213', 'a214', 'a215', 'a216', +'a217', 'a218', 'a219', 'a220', 'a221', 'a222', 'a223', 'a224', 'a225', +'a226', 'a227', 'a228', 'a229', 'a230', 'a231', 'a232', 'a233', 'a234', +'a235', 'a236', 'a237', 'a238', 'a239', 'a240', 'a241', 'a242', 'a243', +'a244', 'a245', 'a246', 'a247', 'a248', 'a249', 'a250', 'a251', 'a252', +'a253', 'a254', 'a255', 'a256'), +t1_FLOAT FLOAT, +t1_FLOAT_UNSIGNED FLOAT UNSIGNED, +t1_INT INT, +t1_INT_UNSIGNED INT UNSIGNED, +t1_LONGBLOB LONGBLOB, +t1_LONGTEXT LONGTEXT, +t1_MEDIUMBLOB MEDIUMBLOB, +t1_MEDIUMINT MEDIUMINT, +t1_MEDIUMINT_UNSIGNED MEDIUMINT UNSIGNED, +t1_MEDIUMTEXT MEDIUMTEXT, +t1_SET SET('a', 'b', 'c'), +t1_SET_BINARY SET('a','b') BINARY, +t1_SET_9 SET('a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9'), +t1_SMALLINT SMALLINT, +t1_SMALLINT_UNSIGNED SMALLINT UNSIGNED, +t1_TEXT TEXT, +t1_TIME TIME, +t1_TIME_4 TIME(4), +t1_TIMESTAMP TIMESTAMP, +t1_TIMESTAMP_5 TIMESTAMP(5), +t1_TINYBLOB TINYBLOB, +t1_TINYINT TINYINT, +t1_TINYINT_UNSIGNED TINYINT UNSIGNED, +t1_TINYTEXT TINYTEXT, +t1_VARBINARY_100 VARBINARY(100), +t1_VARCHAR_10 VARCHAR(10), +t1_VARCHAR_10_BINARY VARCHAR(10) BINARY, +t1_VARCHAR_500 VARCHAR(500), +t1_VARCHAR_500_BINARY VARCHAR(500) BINARY, +t1_YEAR_2 YEAR(2), +t1_YEAR_4 YEAR(4) +) ENGINE=InnoDB; +Warnings: +Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead +SELECT +name, +CASE mtype +WHEN 1 THEN "DATA_VARCHAR" + WHEN 2 THEN "DATA_CHAR" + WHEN 3 THEN "DATA_FIXBINARY" + WHEN 4 THEN "DATA_BINARY" + WHEN 5 THEN "DATA_BLOB" + WHEN 6 THEN "DATA_INT" + WHEN 7 THEN "DATA_SYS_CHILD" + WHEN 8 THEN "DATA_SYS" + WHEN 9 THEN "DATA_FLOAT" + WHEN 10 THEN "DATA_DOUBLE" + WHEN 11 THEN "DATA_DECIMAL" + WHEN 12 THEN "DATA_VARMYSQL" + WHEN 13 THEN "DATA_MYSQL" + WHEN 63 THEN "DATA_MTYPE_MAX" + ELSE mtype +END AS mtype, +IF((prtype & 512) = 512,"UNSIGNED","") AS is_unsigned +FROM information_schema.INNODB_SYS_COLUMNS +WHERE name LIKE "t1\_%" +ORDER BY name; +name mtype is_unsigned +t1_BIGINT DATA_INT +t1_BIGINT_UNSIGNED DATA_INT UNSIGNED +t1_BINARY_100 DATA_FIXBINARY +t1_BIT_2 DATA_FIXBINARY UNSIGNED +t1_BIT_20 DATA_FIXBINARY UNSIGNED +t1_BLOB DATA_BLOB +t1_CHAR_100 DATA_CHAR +t1_CHAR_100_BINARY DATA_MYSQL +t1_DATE DATA_INT +t1_DATETIME DATA_INT +t1_DATETIME_6 DATA_FIXBINARY +t1_DECIMAL_10_3 DATA_FIXBINARY +t1_DECIMAL_10_3_UNSIGNED DATA_FIXBINARY UNSIGNED +t1_DOUBLE DATA_DOUBLE +t1_DOUBLE_UNSIGNED DATA_DOUBLE UNSIGNED +t1_ENUM DATA_INT UNSIGNED +t1_ENUM_256 DATA_INT UNSIGNED +t1_ENUM_BINARY DATA_INT UNSIGNED +t1_FLOAT DATA_FLOAT +t1_FLOAT_UNSIGNED DATA_FLOAT UNSIGNED +t1_INT DATA_INT +t1_INT_UNSIGNED DATA_INT UNSIGNED +t1_LONGBLOB DATA_BLOB +t1_LONGTEXT DATA_BLOB +t1_MEDIUMBLOB DATA_BLOB +t1_MEDIUMINT DATA_INT +t1_MEDIUMINT_UNSIGNED DATA_INT UNSIGNED +t1_MEDIUMTEXT DATA_BLOB +t1_SET DATA_INT UNSIGNED +t1_SET_9 DATA_INT UNSIGNED +t1_SET_BINARY DATA_INT UNSIGNED +t1_SMALLINT DATA_INT +t1_SMALLINT_UNSIGNED DATA_INT UNSIGNED +t1_TEXT DATA_BLOB +t1_TIME DATA_INT +t1_TIMESTAMP DATA_INT UNSIGNED +t1_TIMESTAMP_5 DATA_FIXBINARY UNSIGNED +t1_TIME_4 DATA_FIXBINARY +t1_TINYBLOB DATA_BLOB +t1_TINYINT DATA_INT +t1_TINYINT_UNSIGNED DATA_INT UNSIGNED +t1_TINYTEXT DATA_BLOB +t1_VARBINARY_100 DATA_BINARY +t1_VARCHAR_10 DATA_VARCHAR +t1_VARCHAR_10_BINARY DATA_VARMYSQL +t1_VARCHAR_500 DATA_VARCHAR +t1_VARCHAR_500_BINARY DATA_VARMYSQL +t1_YEAR_2 DATA_INT UNSIGNED +t1_YEAR_4 DATA_INT UNSIGNED +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/1byte_data_int.test b/mysql-test/suite/innodb/t/1byte_data_int.test deleted file mode 100644 index 26ca8a53283..00000000000 --- a/mysql-test/suite/innodb/t/1byte_data_int.test +++ /dev/null @@ -1,25 +0,0 @@ ---source include/have_innodb.inc - ---echo # Create a table with a 1-byte ENUM, 1-byte SET, and TINYINT UNSIGNED. - -CREATE TABLE t1 -( - t1_enum ENUM("a", "b", "c"), - t1_set SET("a", "b", "c"), - t1_tinyint_s TINYINT, - t1_tinyint_u TINYINT UNSIGNED -) ENGINE=InnoDB; - ---echo # All t1 fields' mtypes should be 6 (DATA_INT). - -SELECT - name, - mtype, - (prtype & 512) = 512 AS is_unsigned -FROM information_schema.INNODB_SYS_COLUMNS -WHERE name LIKE "t1\_%" -ORDER BY name; - ---echo # Cleanup - -DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/1byte_data_int.opt b/mysql-test/suite/innodb/t/data_types.opt index 3ad568c816e..3ad568c816e 100644 --- a/mysql-test/suite/innodb/t/1byte_data_int.opt +++ b/mysql-test/suite/innodb/t/data_types.opt diff --git a/mysql-test/suite/innodb/t/data_types.test b/mysql-test/suite/innodb/t/data_types.test new file mode 100644 index 00000000000..0978146361c --- /dev/null +++ b/mysql-test/suite/innodb/t/data_types.test @@ -0,0 +1,118 @@ +# +# MDEV-5248 Serious incompatibility and data corruption of DATETIME and DATE types due to get_innobase_type_from_mysql_type refactor combined with InnoDB Online DDL +# + +# +# This test records what *internal type codes* innodb is using for every +# MariaDB data type. THEY MUST ALWAYS BE THE SAME AND NEVER CHANGE! +# Otherwise we create a compatibility problem and possible silent data +# corruption too, see MDEV-5248 +# + +--source include/have_innodb.inc + +CREATE TABLE t1 +( + t1_BIGINT BIGINT, + t1_BIGINT_UNSIGNED BIGINT UNSIGNED, + t1_BINARY_100 BINARY(100), + t1_BIT_2 BIT(2), + t1_BIT_20 BIT(20), + t1_BLOB BLOB, + t1_CHAR_100 CHAR(100), + t1_CHAR_100_BINARY CHAR(100) BINARY, + t1_DATE DATE, + t1_DATETIME DATETIME, + t1_DATETIME_6 DATETIME(6), + t1_DECIMAL_10_3 DECIMAL(10,3), + t1_DECIMAL_10_3_UNSIGNED DECIMAL(10,3) UNSIGNED, + t1_DOUBLE DOUBLE, + t1_DOUBLE_UNSIGNED DOUBLE UNSIGNED, + t1_ENUM ENUM('a', 'b', 'c'), + t1_ENUM_BINARY ENUM('a','b') BINARY, + t1_ENUM_256 ENUM('a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', + 'a10', 'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a17', 'a18', 'a19', + 'a20', 'a21', 'a22', 'a23', 'a24', 'a25', 'a26', 'a27', 'a28', 'a29', + 'a30', 'a31', 'a32', 'a33', 'a34', 'a35', 'a36', 'a37', 'a38', 'a39', + 'a40', 'a41', 'a42', 'a43', 'a44', 'a45', 'a46', 'a47', 'a48', 'a49', + 'a50', 'a51', 'a52', 'a53', 'a54', 'a55', 'a56', 'a57', 'a58', 'a59', + 'a60', 'a61', 'a62', 'a63', 'a64', 'a65', 'a66', 'a67', 'a68', 'a69', + 'a70', 'a71', 'a72', 'a73', 'a74', 'a75', 'a76', 'a77', 'a78', 'a79', + 'a80', 'a81', 'a82', 'a83', 'a84', 'a85', 'a86', 'a87', 'a88', 'a89', + 'a90', 'a91', 'a92', 'a93', 'a94', 'a95', 'a96', 'a97', 'a98', 'a99', + 'a100', 'a101', 'a102', 'a103', 'a104', 'a105', 'a106', 'a107', 'a108', + 'a109', 'a110', 'a111', 'a112', 'a113', 'a114', 'a115', 'a116', 'a117', + 'a118', 'a119', 'a120', 'a121', 'a122', 'a123', 'a124', 'a125', 'a126', + 'a127', 'a128', 'a129', 'a130', 'a131', 'a132', 'a133', 'a134', 'a135', + 'a136', 'a137', 'a138', 'a139', 'a140', 'a141', 'a142', 'a143', 'a144', + 'a145', 'a146', 'a147', 'a148', 'a149', 'a150', 'a151', 'a152', 'a153', + 'a154', 'a155', 'a156', 'a157', 'a158', 'a159', 'a160', 'a161', 'a162', + 'a163', 'a164', 'a165', 'a166', 'a167', 'a168', 'a169', 'a170', 'a171', + 'a172', 'a173', 'a174', 'a175', 'a176', 'a177', 'a178', 'a179', 'a180', + 'a181', 'a182', 'a183', 'a184', 'a185', 'a186', 'a187', 'a188', 'a189', + 'a190', 'a191', 'a192', 'a193', 'a194', 'a195', 'a196', 'a197', 'a198', + 'a199', 'a200', 'a201', 'a202', 'a203', 'a204', 'a205', 'a206', 'a207', + 'a208', 'a209', 'a210', 'a211', 'a212', 'a213', 'a214', 'a215', 'a216', + 'a217', 'a218', 'a219', 'a220', 'a221', 'a222', 'a223', 'a224', 'a225', + 'a226', 'a227', 'a228', 'a229', 'a230', 'a231', 'a232', 'a233', 'a234', + 'a235', 'a236', 'a237', 'a238', 'a239', 'a240', 'a241', 'a242', 'a243', + 'a244', 'a245', 'a246', 'a247', 'a248', 'a249', 'a250', 'a251', 'a252', + 'a253', 'a254', 'a255', 'a256'), + t1_FLOAT FLOAT, + t1_FLOAT_UNSIGNED FLOAT UNSIGNED, + t1_INT INT, + t1_INT_UNSIGNED INT UNSIGNED, + t1_LONGBLOB LONGBLOB, + t1_LONGTEXT LONGTEXT, + t1_MEDIUMBLOB MEDIUMBLOB, + t1_MEDIUMINT MEDIUMINT, + t1_MEDIUMINT_UNSIGNED MEDIUMINT UNSIGNED, + t1_MEDIUMTEXT MEDIUMTEXT, + t1_SET SET('a', 'b', 'c'), + t1_SET_BINARY SET('a','b') BINARY, + t1_SET_9 SET('a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9'), + t1_SMALLINT SMALLINT, + t1_SMALLINT_UNSIGNED SMALLINT UNSIGNED, + t1_TEXT TEXT, + t1_TIME TIME, + t1_TIME_4 TIME(4), + t1_TIMESTAMP TIMESTAMP, + t1_TIMESTAMP_5 TIMESTAMP(5), + t1_TINYBLOB TINYBLOB, + t1_TINYINT TINYINT, + t1_TINYINT_UNSIGNED TINYINT UNSIGNED, + t1_TINYTEXT TINYTEXT, + t1_VARBINARY_100 VARBINARY(100), + t1_VARCHAR_10 VARCHAR(10), + t1_VARCHAR_10_BINARY VARCHAR(10) BINARY, + t1_VARCHAR_500 VARCHAR(500), + t1_VARCHAR_500_BINARY VARCHAR(500) BINARY, + t1_YEAR_2 YEAR(2), + t1_YEAR_4 YEAR(4) +) ENGINE=InnoDB; + +SELECT + name, + CASE mtype + WHEN 1 THEN "DATA_VARCHAR" + WHEN 2 THEN "DATA_CHAR" + WHEN 3 THEN "DATA_FIXBINARY" + WHEN 4 THEN "DATA_BINARY" + WHEN 5 THEN "DATA_BLOB" + WHEN 6 THEN "DATA_INT" + WHEN 7 THEN "DATA_SYS_CHILD" + WHEN 8 THEN "DATA_SYS" + WHEN 9 THEN "DATA_FLOAT" + WHEN 10 THEN "DATA_DOUBLE" + WHEN 11 THEN "DATA_DECIMAL" + WHEN 12 THEN "DATA_VARMYSQL" + WHEN 13 THEN "DATA_MYSQL" + WHEN 63 THEN "DATA_MTYPE_MAX" + ELSE mtype + END AS mtype, + IF((prtype & 512) = 512,"UNSIGNED","") AS is_unsigned +FROM information_schema.INNODB_SYS_COLUMNS +WHERE name LIKE "t1\_%" +ORDER BY name; + +DROP TABLE t1; diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index ed10525b07d..25bcc87d93c 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -176,7 +176,7 @@ dict_stats_persistent_storage_check( DATA_NOT_NULL, 192}, {"last_update", DATA_INT, - DATA_NOT_NULL | DATA_UNSIGNED, 4}, + DATA_NOT_NULL, 4}, {"n_rows", DATA_INT, DATA_NOT_NULL | DATA_UNSIGNED, 8}, @@ -207,7 +207,7 @@ dict_stats_persistent_storage_check( DATA_NOT_NULL, 192}, {"last_update", DATA_INT, - DATA_NOT_NULL | DATA_UNSIGNED, 4}, + DATA_NOT_NULL, 4}, {"stat_name", DATA_VARMYSQL, DATA_NOT_NULL, 64*3}, diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 9b6c96078ac..82421d2d725 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5745,67 +5745,92 @@ get_innobase_type_from_mysql_type( 8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to the type */ - compile_time_assert((ulint)MYSQL_TYPE_STRING < 256); - compile_time_assert((ulint)MYSQL_TYPE_VAR_STRING < 256); - compile_time_assert((ulint)MYSQL_TYPE_DOUBLE < 256); - compile_time_assert((ulint)MYSQL_TYPE_FLOAT < 256); - compile_time_assert((ulint)MYSQL_TYPE_DECIMAL < 256); + DBUG_ASSERT((ulint)MYSQL_TYPE_STRING < 256); + DBUG_ASSERT((ulint)MYSQL_TYPE_VAR_STRING < 256); + DBUG_ASSERT((ulint)MYSQL_TYPE_DOUBLE < 256); + DBUG_ASSERT((ulint)MYSQL_TYPE_FLOAT < 256); + DBUG_ASSERT((ulint)MYSQL_TYPE_DECIMAL < 256); - *unsigned_flag = 0; + if (field->flags & UNSIGNED_FLAG) { - switch (field->key_type()) { - case HA_KEYTYPE_USHORT_INT: - case HA_KEYTYPE_ULONG_INT: - case HA_KEYTYPE_UINT24: - case HA_KEYTYPE_ULONGLONG: *unsigned_flag = DATA_UNSIGNED; - /* fall through */ - case HA_KEYTYPE_SHORT_INT: - case HA_KEYTYPE_LONG_INT: - case HA_KEYTYPE_INT24: - case HA_KEYTYPE_INT8: - case HA_KEYTYPE_LONGLONG: + } else { + *unsigned_flag = 0; + } + + if (field->real_type() == MYSQL_TYPE_ENUM + || field->real_type() == MYSQL_TYPE_SET) { + + /* MySQL has field->type() a string type for these, but the + data is actually internally stored as an unsigned integer + code! */ + + *unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned + flag set to zero, even though + internally this is an unsigned + integer type */ return(DATA_INT); - case HA_KEYTYPE_FLOAT: - return(DATA_FLOAT); - case HA_KEYTYPE_DOUBLE: - return(DATA_DOUBLE); - case HA_KEYTYPE_BINARY: - if (field->type() == MYSQL_TYPE_TINY || - field->real_type() == MYSQL_TYPE_ENUM || - field->real_type() == MYSQL_TYPE_SET - ) - { // compatibility workaround - *unsigned_flag= DATA_UNSIGNED; - return DATA_INT; - } - return(DATA_FIXBINARY); - case HA_KEYTYPE_VARBINARY2: - if (field->type() != MYSQL_TYPE_VARCHAR) - return(DATA_BLOB); - /* fall through */ - case HA_KEYTYPE_VARBINARY1: - return(DATA_BINARY); - case HA_KEYTYPE_VARTEXT2: - if (field->type() != MYSQL_TYPE_VARCHAR) - return(DATA_BLOB); - /* fall through */ - case HA_KEYTYPE_VARTEXT1: - if (field->charset() == &my_charset_latin1) { + } + + switch (field->type()) { + /* NOTE that we only allow string types in DATA_MYSQL and + DATA_VARMYSQL */ + case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */ + case MYSQL_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */ + if (field->binary()) { + return(DATA_BINARY); + } else if (strcmp(field->charset()->name, + "latin1_swedish_ci") == 0) { return(DATA_VARCHAR); } else { return(DATA_VARMYSQL); } - case HA_KEYTYPE_TEXT: - if (field->charset() == &my_charset_latin1) { + case MYSQL_TYPE_BIT: + case MYSQL_TYPE_STRING: if (field->binary()) { + + return(DATA_FIXBINARY); + } else if (strcmp(field->charset()->name, + "latin1_swedish_ci") == 0) { return(DATA_CHAR); } else { return(DATA_MYSQL); } - case HA_KEYTYPE_NUM: + case MYSQL_TYPE_NEWDECIMAL: + return(DATA_FIXBINARY); + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_LONGLONG: + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_YEAR: + case MYSQL_TYPE_NEWDATE: + return(DATA_INT); + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATETIME: + if (field->key_type() == HA_KEYTYPE_BINARY) + return(DATA_FIXBINARY); + else + return(DATA_INT); + case MYSQL_TYPE_FLOAT: + return(DATA_FLOAT); + case MYSQL_TYPE_DOUBLE: + return(DATA_DOUBLE); + case MYSQL_TYPE_DECIMAL: return(DATA_DECIMAL); - case HA_KEYTYPE_BIT: - case HA_KEYTYPE_END: + case MYSQL_TYPE_GEOMETRY: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_LONG_BLOB: + return(DATA_BLOB); + case MYSQL_TYPE_NULL: + /* MySQL currently accepts "NULL" datatype, but will + reject such datatype in the next release. We will cope + with it and not trigger assertion failure in 5.1 */ + break; + default: ut_error; } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index dd6525ae7c0..a120534b36d 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -347,6 +347,32 @@ ha_innobase::check_if_supported_inplace_alter( } } + /* + InnoDB in different MariaDB versions was generating different mtype + codes for certain types. In some cases the signed/unsigned bit was + generated differently too. + + Online ALTER would change the mtype/unsigned_flag (to what the + current code generates) without changing the underlying data + represenation, and it might result in data corruption. + + Don't do online ALTER if mtype/unsigned_flag are wrong. + */ + for (ulint i = 0; i < table->s->fields; i++) { + const Field* field = table->field[i]; + const dict_col_t* col = dict_table_get_nth_col(prebuilt->table, i); + ulint unsigned_flag; + if (col->mtype != get_innobase_type_from_mysql_type(&unsigned_flag, field)) { + + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + } + + if ((col->prtype & DATA_UNSIGNED) != unsigned_flag) { + + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + } + } + /* We should be able to do the operation in-place. See if we can do it online (LOCK=NONE). */ bool online = true; |