summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-11-13 22:58:19 +0100
committerSergei Golubchik <sergii@pisem.net>2013-11-13 22:58:19 +0100
commitc155890af90ec75555fa485387a0cf11120175a6 (patch)
tree5b06186dc99f9dd83a5aac2c98c9d73eed5c7742
parent80137baf2fe262607e91e7a518789f12ad815819 (diff)
downloadmariadb-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.result23
-rw-r--r--mysql-test/suite/innodb/r/data_types.result155
-rw-r--r--mysql-test/suite/innodb/t/1byte_data_int.test25
-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.test118
-rw-r--r--storage/innobase/dict/dict0stats.cc4
-rw-r--r--storage/innobase/handler/ha_innodb.cc121
-rw-r--r--storage/innobase/handler/handler0alter.cc26
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;