Skip to content

Commit 906ce09

Browse files
committed
MDEV-7049 MySQL#74585 - InnoDB: Failing assertion: *mbmaxlen < 5 in file ha_innodb.cc line 1904
InnoDB limited the maximum number of bytes per character to 4. But, the filename character set that was introduced in MySQL 5.1 uses up to 5 bytes per character. To allow InnoDB tables to be created with wider characters, let us split the mbminmaxlen fields into mbminlen, mbmaxlen, and increase the limit to 7 bytes per character. This will increase the payload size of dtype_t and dict_col_t by one bit. The storage size will be unchanged (54 bits and 77 bits will use the same number of bytes as the previous sizes 53 and 76 bits).
1 parent 6c60c80 commit 906ce09

31 files changed

+181
-338
lines changed

mysql-test/suite/innodb/r/innodb.result

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
create temporary table t (a char(1) character set filename) engine=innodb;
2+
drop temporary table t;
13
set optimizer_switch = 'mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
24
drop table if exists t1,t2,t3,t4;
35
drop database if exists mysqltest;

mysql-test/suite/innodb/t/innodb.test

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,11 @@
1-
#######################################################################
2-
# #
3-
# Please, DO NOT TOUCH this file as well as the innodb.result file. #
4-
# These files are to be modified ONLY BY INNOBASE guys. #
5-
# #
6-
# Use innodb_mysql.[test|result] files instead. #
7-
# #
8-
# If nevertheless you need to make some changes here, please, forward #
9-
# your commit message #
10-
# To: innodb_dev_ww@oracle.com #
11-
# Cc: dev-innodb@mysql.com #
12-
# (otherwise your changes may be erased). #
13-
# #
14-
#######################################################################
15-
161
-- source include/have_innodb.inc
172
let $MYSQLD_DATADIR= `select @@datadir`;
183
let collation=utf8_unicode_ci;
194
--source include/have_collation.inc
205

6+
create temporary table t (a char(1) character set filename) engine=innodb;
7+
drop temporary table t;
8+
219
set optimizer_switch = 'mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
2210

2311
# Save the original values of some variables in order to be able to
@@ -2546,18 +2534,3 @@ show status like "handler_read_key";
25462534
select f1 from t1;
25472535
show status like "handler_read_key";
25482536
drop table t1;
2549-
2550-
#######################################################################
2551-
# #
2552-
# Please, DO NOT TOUCH this file as well as the innodb.result file. #
2553-
# These files are to be modified ONLY BY INNOBASE guys. #
2554-
# #
2555-
# Use innodb_mysql.[test|result] files instead. #
2556-
# #
2557-
# If nevertheless you need to make some changes here, please, forward #
2558-
# your commit message #
2559-
# To: innodb_dev_ww@oracle.com #
2560-
# Cc: dev-innodb@mysql.com #
2561-
# (otherwise your changes may be erased). #
2562-
# #
2563-
#######################################################################

storage/innobase/data/data0type.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
4+
Copyright (c) 2018, MariaDB Corporation.
45
56
This program is free software; you can redistribute it and/or modify it under
67
the terms of the GNU General Public License as published by the Free Software
@@ -49,18 +50,17 @@ ulint
4950
dtype_get_at_most_n_mbchars(
5051
/*========================*/
5152
ulint prtype, /*!< in: precise type */
52-
ulint mbminmaxlen, /*!< in: minimum and maximum length of
53-
a multi-byte character */
53+
ulint mbminlen, /*!< in: minimum length of
54+
a multi-byte character, in bytes */
55+
ulint mbmaxlen, /*!< in: maximum length of
56+
a multi-byte character, in bytes */
5457
ulint prefix_len, /*!< in: length of the requested
5558
prefix, in characters, multiplied by
5659
dtype_get_mbmaxlen(dtype) */
5760
ulint data_len, /*!< in: length of str (in bytes) */
5861
const char* str) /*!< in: the string whose prefix
5962
length is being determined */
6063
{
61-
ulint mbminlen = DATA_MBMINLEN(mbminmaxlen);
62-
ulint mbmaxlen = DATA_MBMAXLEN(mbminmaxlen);
63-
6464
ut_a(data_len != UNIV_SQL_NULL);
6565
ut_ad(!mbmaxlen || !(prefix_len % mbmaxlen));
6666

storage/innobase/dict/dict0mem.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
4+
Copyright (c) 2018, MariaDB Corporation.
45
56
This program is free software; you can redistribute it and/or modify it under
67
the terms of the GNU General Public License as published by the Free Software
@@ -251,7 +252,8 @@ dict_mem_fill_column_struct(
251252
column->len = (unsigned int) col_len;
252253
#ifndef UNIV_HOTBACKUP
253254
dtype_get_mblen(mtype, prtype, &mbminlen, &mbmaxlen);
254-
dict_col_set_mbminmaxlen(column, mbminlen, mbmaxlen);
255+
column->mbminlen = mbminlen;
256+
column->mbmaxlen = mbmaxlen;
255257
#endif /* !UNIV_HOTBACKUP */
256258
}
257259

storage/innobase/handler/handler0alter.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved.
4+
Copyright (c) 2018, MariaDB Corporation.
45
56
This program is free software; you can redistribute it and/or modify it under
67
the terms of the GNU General Public License as published by the Free Software
@@ -99,8 +100,7 @@ innobase_col_to_mysql(
99100
#ifdef UNIV_DEBUG
100101
case DATA_MYSQL:
101102
ut_ad(flen >= len);
102-
ut_ad(DATA_MBMAXLEN(col->mbminmaxlen)
103-
>= DATA_MBMINLEN(col->mbminmaxlen));
103+
ut_ad(col->mbmaxlen >= col->mbminlen);
104104
memcpy(dest, data, len);
105105
break;
106106

storage/innobase/include/data0type.h

Lines changed: 15 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
4+
Copyright (c) 2018, MariaDB Corporation.
45
56
This program is free software; you can redistribute it and/or modify it under
67
the terms of the GNU General Public License as published by the Free Software
@@ -169,18 +170,7 @@ store the charset-collation number; one byte is left unused, though */
169170
#define DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 6
170171

171172
/* Maximum multi-byte character length in bytes, plus 1 */
172-
#define DATA_MBMAX 5
173-
174-
/* Pack mbminlen, mbmaxlen to mbminmaxlen. */
175-
#define DATA_MBMINMAXLEN(mbminlen, mbmaxlen) \
176-
((mbmaxlen) * DATA_MBMAX + (mbminlen))
177-
/* Get mbminlen from mbminmaxlen. Cast the result of UNIV_EXPECT to ulint
178-
because in GCC it returns a long. */
179-
#define DATA_MBMINLEN(mbminmaxlen) ((ulint) \
180-
UNIV_EXPECT(((mbminmaxlen) % DATA_MBMAX), \
181-
1))
182-
/* Get mbmaxlen from mbminmaxlen. */
183-
#define DATA_MBMAXLEN(mbminmaxlen) ((ulint) ((mbminmaxlen) / DATA_MBMAX))
173+
#define DATA_MBMAX 8
184174

185175
#ifndef UNIV_HOTBACKUP
186176
/*********************************************************************//**
@@ -201,8 +191,10 @@ ulint
201191
dtype_get_at_most_n_mbchars(
202192
/*========================*/
203193
ulint prtype, /*!< in: precise type */
204-
ulint mbminmaxlen, /*!< in: minimum and maximum length of
205-
a multi-byte character */
194+
ulint mbminlen, /*!< in: minimum length of
195+
a multi-byte character, in bytes */
196+
ulint mbmaxlen, /*!< in: maximum length of
197+
a multi-byte character, in bytes */
206198
ulint prefix_len, /*!< in: length of the requested
207199
prefix, in characters, multiplied by
208200
dtype_get_mbmaxlen(dtype) */
@@ -347,19 +339,6 @@ dtype_get_mbmaxlen(
347339
/*===============*/
348340
const dtype_t* type); /*!< in: type */
349341
/*********************************************************************//**
350-
Sets the minimum and maximum length of a character, in bytes. */
351-
UNIV_INLINE
352-
void
353-
dtype_set_mbminmaxlen(
354-
/*==================*/
355-
dtype_t* type, /*!< in/out: type */
356-
ulint mbminlen, /*!< in: minimum length of a char,
357-
in bytes, or 0 if this is not
358-
a character type */
359-
ulint mbmaxlen); /*!< in: maximum length of a char,
360-
in bytes, or 0 if this is not
361-
a character type */
362-
/*********************************************************************//**
363342
Gets the padding character code for the type.
364343
@return padding character code, or ULINT_UNDEFINED if no padding specified */
365344
UNIV_INLINE
@@ -379,7 +358,9 @@ dtype_get_fixed_size_low(
379358
ulint mtype, /*!< in: main type */
380359
ulint prtype, /*!< in: precise type */
381360
ulint len, /*!< in: length */
382-
ulint mbminmaxlen, /*!< in: minimum and maximum length of a
361+
ulint mbminlen, /*!< in: minimum length of a
362+
multibyte character, in bytes */
363+
ulint mbmaxlen, /*!< in: maximum length of a
383364
multibyte character, in bytes */
384365
ulint comp); /*!< in: nonzero=ROW_FORMAT=COMPACT */
385366
#ifndef UNIV_HOTBACKUP
@@ -393,8 +374,8 @@ dtype_get_min_size_low(
393374
ulint mtype, /*!< in: main type */
394375
ulint prtype, /*!< in: precise type */
395376
ulint len, /*!< in: length */
396-
ulint mbminmaxlen); /*!< in: minimum and maximum length of a
397-
multibyte character */
377+
ulint mbminlen, /*!< in: minimum length of a character */
378+
ulint mbmaxlen); /*!< in: maximum length of a character */
398379
/***********************************************************************//**
399380
Returns the maximum size of a data type. Note: types in system tables may be
400381
incomplete and return incorrect information.
@@ -497,11 +478,10 @@ struct dtype_struct{
497478
the string, MySQL uses 1 or 2
498479
bytes to store the string length) */
499480
#ifndef UNIV_HOTBACKUP
500-
unsigned mbminmaxlen:5; /*!< minimum and maximum length of a
501-
character, in bytes;
502-
DATA_MBMINMAXLEN(mbminlen,mbmaxlen);
503-
mbminlen=DATA_MBMINLEN(mbminmaxlen);
504-
mbmaxlen=DATA_MBMINLEN(mbminmaxlen) */
481+
unsigned mbminlen:3; /*!< minimum length of a character,
482+
in bytes */
483+
unsigned mbmaxlen:3; /*!< maximum length of a character,
484+
in bytes */
505485
#endif /* !UNIV_HOTBACKUP */
506486
};
507487

storage/innobase/include/data0type.ic

Lines changed: 16 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*****************************************************************************
22

33
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
4+
Copyright (c) 2018, MariaDB Corporation.
45

56
This program is free software; you can redistribute it and/or modify it under
67
the terms of the GNU General Public License as published by the Free Software
@@ -100,27 +101,6 @@ dtype_get_mblen(
100101
}
101102
}
102103

103-
/*********************************************************************//**
104-
Sets the minimum and maximum length of a character, in bytes. */
105-
UNIV_INLINE
106-
void
107-
dtype_set_mbminmaxlen(
108-
/*==================*/
109-
dtype_t* type, /*!< in/out: type */
110-
ulint mbminlen, /*!< in: minimum length of a char,
111-
in bytes, or 0 if this is not
112-
a character type */
113-
ulint mbmaxlen) /*!< in: maximum length of a char,
114-
in bytes, or 0 if this is not
115-
a character type */
116-
{
117-
ut_ad(mbminlen < DATA_MBMAX);
118-
ut_ad(mbmaxlen < DATA_MBMAX);
119-
ut_ad(mbminlen <= mbmaxlen);
120-
121-
type->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen);
122-
}
123-
124104
/*********************************************************************//**
125105
Compute the mbminlen and mbmaxlen members of a data type structure. */
126106
UNIV_INLINE
@@ -133,7 +113,8 @@ dtype_set_mblen(
133113
ulint mbmaxlen;
134114

135115
dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen);
136-
dtype_set_mbminmaxlen(type, mbminlen, mbmaxlen);
116+
type->mbminlen = mbminlen;
117+
type->mbmaxlen = mbmaxlen;
137118

138119
ut_ad(dtype_validate(type));
139120
}
@@ -229,8 +210,7 @@ dtype_get_mbminlen(
229210
/*===============*/
230211
const dtype_t* type) /*!< in: type */
231212
{
232-
ut_ad(type);
233-
return(DATA_MBMINLEN(type->mbminmaxlen));
213+
return type->mbminlen;
234214
}
235215
/*********************************************************************//**
236216
Gets the maximum length of a character, in bytes.
@@ -242,8 +222,7 @@ dtype_get_mbmaxlen(
242222
/*===============*/
243223
const dtype_t* type) /*!< in: type */
244224
{
245-
ut_ad(type);
246-
return(DATA_MBMAXLEN(type->mbminmaxlen));
225+
return type->mbmaxlen;
247226
}
248227

249228
/*********************************************************************//**
@@ -424,8 +403,10 @@ dtype_get_fixed_size_low(
424403
ulint mtype, /*!< in: main type */
425404
ulint prtype, /*!< in: precise type */
426405
ulint len, /*!< in: length */
427-
ulint mbminmaxlen, /*!< in: minimum and maximum length of
428-
a multibyte character, in bytes */
406+
ulint mbminlen, /*!< in: minimum length of a
407+
multibyte character, in bytes */
408+
ulint mbmaxlen, /*!< in: maximum length of a
409+
multibyte character, in bytes */
429410
ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */
430411
{
431412
switch (mtype) {
@@ -466,11 +447,10 @@ dtype_get_fixed_size_low(
466447
dtype_get_charset_coll(prtype),
467448
&i_mbminlen, &i_mbmaxlen);
468449

469-
ut_ad(DATA_MBMINMAXLEN(i_mbminlen, i_mbmaxlen)
470-
== mbminmaxlen);
450+
ut_ad(i_mbminlen == mbminlen);
451+
ut_ad(i_mbmaxlen == mbmaxlen);
471452
#endif /* UNIV_DEBUG */
472-
if (DATA_MBMINLEN(mbminmaxlen)
473-
== DATA_MBMAXLEN(mbminmaxlen)) {
453+
if (mbminlen == mbmaxlen) {
474454
return(len);
475455
}
476456
}
@@ -502,8 +482,8 @@ dtype_get_min_size_low(
502482
ulint mtype, /*!< in: main type */
503483
ulint prtype, /*!< in: precise type */
504484
ulint len, /*!< in: length */
505-
ulint mbminmaxlen) /*!< in: minimum and maximum length of a
506-
multi-byte character */
485+
ulint mbminlen, /*!< in: minimum length of a character */
486+
ulint mbmaxlen) /*!< in: maximum length of a character */
507487
{
508488
switch (mtype) {
509489
case DATA_SYS:
@@ -533,9 +513,6 @@ dtype_get_min_size_low(
533513
if (prtype & DATA_BINARY_TYPE) {
534514
return(len);
535515
} else {
536-
ulint mbminlen = DATA_MBMINLEN(mbminmaxlen);
537-
ulint mbmaxlen = DATA_MBMAXLEN(mbminmaxlen);
538-
539516
if (mbminlen == mbmaxlen) {
540517
return(len);
541518
}
@@ -606,9 +583,9 @@ dtype_get_sql_null_size(
606583
{
607584
#ifndef UNIV_HOTBACKUP
608585
return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len,
609-
type->mbminmaxlen, comp));
586+
type->mbminlen, type->mbmaxlen, comp));
610587
#else /* !UNIV_HOTBACKUP */
611588
return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len,
612-
0, 0));
589+
0, 0, 0));
613590
#endif /* !UNIV_HOTBACKUP */
614591
}

storage/innobase/include/dict0dict.h

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
4+
Copyright (c) 2018, MariaDB Corporation.
45
56
This program is free software; you can redistribute it and/or modify it under
67
the terms of the GNU General Public License as published by the Free Software
@@ -119,17 +120,6 @@ dict_col_get_mbmaxlen(
119120
/*==================*/
120121
const dict_col_t* col); /*!< in: column */
121122
/*********************************************************************//**
122-
Sets the minimum and maximum number of bytes per character. */
123-
UNIV_INLINE
124-
void
125-
dict_col_set_mbminmaxlen(
126-
/*=====================*/
127-
dict_col_t* col, /*!< in/out: column */
128-
ulint mbminlen, /*!< in: minimum multi-byte
129-
character size, in bytes */
130-
ulint mbmaxlen); /*!< in: minimum multi-byte
131-
character size, in bytes */
132-
/*********************************************************************//**
133123
Gets the column data type. */
134124
UNIV_INLINE
135125
void

0 commit comments

Comments
 (0)