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.
This commit is contained in:
Marko Mäkelä 2018-12-12 13:10:52 +02:00
parent db1210f939
commit e0aebf5cf1
3 changed files with 43 additions and 2 deletions

View file

@ -75,10 +75,13 @@ t1_VARCHAR_10_BINARY VARCHAR(10) BINARY,
t1_VARCHAR_500 VARCHAR(500), t1_VARCHAR_500 VARCHAR(500),
t1_VARCHAR_500_BINARY VARCHAR(500) BINARY, t1_VARCHAR_500_BINARY VARCHAR(500) BINARY,
t1_YEAR_2 YEAR(2), 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; ) ENGINE=InnoDB;
Warnings: Warnings:
Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead
INSERT INTO t1 () VALUES ();
SELECT SELECT
name, name,
CASE mtype CASE mtype
@ -109,6 +112,7 @@ t1_BINARY_100 DATA_FIXBINARY
t1_BIT_2 DATA_FIXBINARY UNSIGNED t1_BIT_2 DATA_FIXBINARY UNSIGNED
t1_BIT_20 DATA_FIXBINARY UNSIGNED t1_BIT_20 DATA_FIXBINARY UNSIGNED
t1_BLOB DATA_BLOB t1_BLOB DATA_BLOB
t1_CHAR_0 DATA_CHAR
t1_CHAR_100 DATA_CHAR t1_CHAR_100 DATA_CHAR
t1_CHAR_100_BINARY DATA_MYSQL t1_CHAR_100_BINARY DATA_MYSQL
t1_DATE DATA_INT t1_DATE DATA_INT
@ -131,6 +135,7 @@ t1_MEDIUMBLOB DATA_BLOB
t1_MEDIUMINT DATA_INT t1_MEDIUMINT DATA_INT
t1_MEDIUMINT_UNSIGNED DATA_INT UNSIGNED t1_MEDIUMINT_UNSIGNED DATA_INT UNSIGNED
t1_MEDIUMTEXT DATA_BLOB t1_MEDIUMTEXT DATA_BLOB
t1_MYSQL_0 DATA_MYSQL
t1_SET DATA_INT UNSIGNED t1_SET DATA_INT UNSIGNED
t1_SET_9 DATA_INT UNSIGNED t1_SET_9 DATA_INT UNSIGNED
t1_SET_BINARY 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_2 DATA_INT UNSIGNED
t1_YEAR_4 DATA_INT UNSIGNED t1_YEAR_4 DATA_INT UNSIGNED
DROP TABLE t1; 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;

View file

@ -88,9 +88,13 @@ CREATE TABLE t1
t1_VARCHAR_500 VARCHAR(500), t1_VARCHAR_500 VARCHAR(500),
t1_VARCHAR_500_BINARY VARCHAR(500) BINARY, t1_VARCHAR_500_BINARY VARCHAR(500) BINARY,
t1_YEAR_2 YEAR(2), 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; ) ENGINE=InnoDB;
INSERT INTO t1 () VALUES ();
SELECT SELECT
name, name,
CASE mtype CASE mtype
@ -116,3 +120,10 @@ WHERE name LIKE "t1\_%"
ORDER BY name; ORDER BY name;
DROP TABLE t1; 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;

View file

@ -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); field_max_size = dict_col_get_max_size(col);
if (UNIV_UNLIKELY(!field_max_size)) { 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 /* SYS_FOREIGN.ID is defined as CHAR in the
InnoDB internal SQL parser, which translates InnoDB internal SQL parser, which translates
into the incorrect VARCHAR(0). InnoDB does into the incorrect VARCHAR(0). InnoDB does