summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-12-12 13:10:52 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2018-12-12 13:21:05 +0200
commite0aebf5cf1c705739a94fe2fecf0b0ed7eb4ba3a (patch)
treed4f3e5ea2fe0f78a410d8bab93fdaa8708e2c5c2
parentdb1210f9399ba97f7ea8ad81ca4f208f99df25c4 (diff)
downloadmariadb-git-e0aebf5cf1c705739a94fe2fecf0b0ed7eb4ba3a.tar.gz
MDEV-17815 Assertion failed in btr_node_ptr_max_size for CHAR(0)
btr_node_ptr_max_size(): Treat CHAR(0) from SQL as a special case. The InnoDB internal SQL parser maps the type "CHAR" to DATA_VARCHAR, but MariaDB does allow CHAR(0) with an empty value, and does enforce the length limitation.
-rw-r--r--mysql-test/suite/innodb/r/data_types.result13
-rw-r--r--mysql-test/suite/innodb/t/data_types.test13
-rw-r--r--storage/innobase/btr/btr0cur.cc19
3 files changed, 43 insertions, 2 deletions
diff --git a/mysql-test/suite/innodb/r/data_types.result b/mysql-test/suite/innodb/r/data_types.result
index 446d37527e5..4e919e37cee 100644
--- a/mysql-test/suite/innodb/r/data_types.result
+++ b/mysql-test/suite/innodb/r/data_types.result
@@ -75,10 +75,13 @@ 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)
+t1_YEAR_4 YEAR(4),
+t1_CHAR_0 CHAR(0),
+t1_MYSQL_0 CHAR(0) CHARACTER SET utf8
) ENGINE=InnoDB;
Warnings:
Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
+INSERT INTO t1 () VALUES ();
SELECT
name,
CASE mtype
@@ -109,6 +112,7 @@ t1_BINARY_100 DATA_FIXBINARY
t1_BIT_2 DATA_FIXBINARY UNSIGNED
t1_BIT_20 DATA_FIXBINARY UNSIGNED
t1_BLOB DATA_BLOB
+t1_CHAR_0 DATA_CHAR
t1_CHAR_100 DATA_CHAR
t1_CHAR_100_BINARY DATA_MYSQL
t1_DATE DATA_INT
@@ -131,6 +135,7 @@ t1_MEDIUMBLOB DATA_BLOB
t1_MEDIUMINT DATA_INT
t1_MEDIUMINT_UNSIGNED DATA_INT UNSIGNED
t1_MEDIUMTEXT DATA_BLOB
+t1_MYSQL_0 DATA_MYSQL
t1_SET DATA_INT UNSIGNED
t1_SET_9 DATA_INT UNSIGNED
t1_SET_BINARY DATA_INT UNSIGNED
@@ -153,3 +158,9 @@ t1_VARCHAR_500_BINARY DATA_VARMYSQL
t1_YEAR_2 DATA_INT UNSIGNED
t1_YEAR_4 DATA_INT UNSIGNED
DROP TABLE t1;
+#
+# MDEV-17815 Assertion failed in btr_node_ptr_max_size for CHAR(0)
+#
+CREATE TABLE t1 (c CHAR(0), KEY(c)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES ('');
+DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/t/data_types.test b/mysql-test/suite/innodb/t/data_types.test
index 0978146361c..c8e80c9db27 100644
--- a/mysql-test/suite/innodb/t/data_types.test
+++ b/mysql-test/suite/innodb/t/data_types.test
@@ -88,9 +88,13 @@ CREATE TABLE t1
t1_VARCHAR_500 VARCHAR(500),
t1_VARCHAR_500_BINARY VARCHAR(500) BINARY,
t1_YEAR_2 YEAR(2),
- t1_YEAR_4 YEAR(4)
+ t1_YEAR_4 YEAR(4),
+ t1_CHAR_0 CHAR(0),
+ t1_MYSQL_0 CHAR(0) CHARACTER SET utf8
) ENGINE=InnoDB;
+INSERT INTO t1 () VALUES ();
+
SELECT
name,
CASE mtype
@@ -116,3 +120,10 @@ WHERE name LIKE "t1\_%"
ORDER BY name;
DROP TABLE t1;
+
+--echo #
+--echo # MDEV-17815 Assertion failed in btr_node_ptr_max_size for CHAR(0)
+--echo #
+CREATE TABLE t1 (c CHAR(0), KEY(c)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES ('');
+DROP TABLE t1;
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index 373328939c2..3f26803d14b 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -753,6 +753,25 @@ static ulint btr_node_ptr_max_size(const dict_index_t* index)
field_max_size = dict_col_get_max_size(col);
if (UNIV_UNLIKELY(!field_max_size)) {
+ switch (col->mtype) {
+ case DATA_CHAR:
+ case DATA_MYSQL:
+ /* CHAR(0) is a possible data type.
+ The InnoDB internal SQL parser maps
+ CHAR to DATA_VARCHAR, so DATA_CHAR (or
+ DATA_MYSQL) is only coming from the
+ MariaDB SQL layer. */
+ if (comp) {
+ /* Add a length byte, because
+ fixed-length empty field are
+ encoded as variable-length.
+ For ROW_FORMAT=REDUNDANT,
+ these bytes were added to
+ rec_max_size before this loop. */
+ rec_max_size++;
+ }
+ continue;
+ }
/* SYS_FOREIGN.ID is defined as CHAR in the
InnoDB internal SQL parser, which translates
into the incorrect VARCHAR(0). InnoDB does