Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
bdab5b66
Commit
bdab5b66
authored
May 22, 2020
by
Alexander Barkov
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/10.1' into 10.2
parents
450a5b33
cb9c49a9
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
284 additions
and
59 deletions
+284
-59
mysql-test/r/ctype_binary.result
mysql-test/r/ctype_binary.result
+93
-0
mysql-test/t/ctype_binary.test
mysql-test/t/ctype_binary.test
+60
-0
sql/table.cc
sql/table.cc
+116
-51
sql/unireg.cc
sql/unireg.cc
+15
-8
No files found.
mysql-test/r/ctype_binary.result
View file @
bdab5b66
...
...
@@ -3172,5 +3172,98 @@ Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 'a' and weight_string(`test`.`t1`.`a`,0,0,1) = 'a'
DROP TABLE t1;
#
# MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed
#
CREATE TABLE t1(a ENUM(0x6100,0x6200,0x6300) CHARACTER SET 'Binary');
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` enum('a\0','b\0','c\0') CHARACTER SET binary DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (1),(2),(3);
SELECT HEX(a) FROM t1 ORDER BY a;
HEX(a)
6100
6200
6300
DROP TABLE t1;
0x00 in the middle or in the end of a value
CREATE TABLE t1 (a ENUM(0x6100));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` enum('a\0') DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (1);
SELECT HEX(a) FROM t1;
HEX(a)
6100
DROP TABLE t1;
CREATE TABLE t1 (a ENUM(0x610062));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` enum('a\0b') DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (1);
SELECT HEX(a) FROM t1;
HEX(a)
610062
DROP TABLE t1;
0x00 in the beginning of the first value:
CREATE TABLE t1 (a ENUM(0x0061));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` enum('\0a') DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES(1);
SELECT HEX(a) FROM t1;
HEX(a)
0061
DROP TABLE t1;
CREATE TABLE t1 (a ENUM(0x0061), b ENUM('b'));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` enum('\0a') DEFAULT NULL,
`b` enum('b') DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (1,1);
SELECT HEX(a), HEX(b) FROM t1;
HEX(a) HEX(b)
0061 62
DROP TABLE t1;
# 0x00 in the beginning of the second (and following) value of the *last* ENUM/SET in the table:
CREATE TABLE t1 (a ENUM('a',0x0061));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` enum('a','\0a') DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (1),(2);
SELECT HEX(a) FROM t1 ORDER BY a;
HEX(a)
61
0061
DROP TABLE t1;
CREATE TABLE t1 (a ENUM('a'), b ENUM('b',0x0061));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` enum('a') DEFAULT NULL,
`b` enum('b','\0a') DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (1,1);
INSERT INTO t1 VALUES (1,2);
SELECT HEX(a), HEX(b) FROM t1 ORDER BY a, b;
HEX(a) HEX(b)
61 62
61 0061
DROP TABLE t1;
0x00 in the beginning of a value of a non-last ENUM/SET causes an error:
CREATE TABLE t1 (a ENUM('a',0x0061), b ENUM('b'));
ERROR HY000: Incorrect information in file: 'DIR/t1.frm'
#
# End of 10.1 tests
#
mysql-test/t/ctype_binary.test
View file @
bdab5b66
...
...
@@ -74,6 +74,66 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE COERCIBILITY(a)=2 AND a='a';
EXPLAIN
EXTENDED
SELECT
*
FROM
t1
WHERE
WEIGHT_STRING
(
a
)
=
'a'
AND
a
=
'a'
;
DROP
TABLE
t1
;
--
echo
#
--
echo
# MDEV-22111 ERROR 1064 & 1033 and SIGSEGV on CREATE TABLE w/ various charsets on 10.4/5 optimized builds | Assertion `(uint) (table_check_constraints - share->check_constraints) == (uint) (share->table_check_constraints - share->field_check_constraints)' failed
--
echo
#
CREATE
TABLE
t1
(
a
ENUM
(
0x6100
,
0x6200
,
0x6300
)
CHARACTER
SET
'Binary'
);
SHOW
CREATE
TABLE
t1
;
INSERT
INTO
t1
VALUES
(
1
),(
2
),(
3
);
SELECT
HEX
(
a
)
FROM
t1
ORDER
BY
a
;
DROP
TABLE
t1
;
--
echo
0x00
in
the
middle
or
in
the
end
of
a
value
CREATE
TABLE
t1
(
a
ENUM
(
0x6100
));
SHOW
CREATE
TABLE
t1
;
INSERT
INTO
t1
VALUES
(
1
);
SELECT
HEX
(
a
)
FROM
t1
;
DROP
TABLE
t1
;
CREATE
TABLE
t1
(
a
ENUM
(
0x610062
));
SHOW
CREATE
TABLE
t1
;
INSERT
INTO
t1
VALUES
(
1
);
SELECT
HEX
(
a
)
FROM
t1
;
DROP
TABLE
t1
;
--
echo
0x00
in
the
beginning
of
the
first
value
:
CREATE
TABLE
t1
(
a
ENUM
(
0x0061
));
SHOW
CREATE
TABLE
t1
;
INSERT
INTO
t1
VALUES
(
1
);
SELECT
HEX
(
a
)
FROM
t1
;
DROP
TABLE
t1
;
CREATE
TABLE
t1
(
a
ENUM
(
0x0061
),
b
ENUM
(
'b'
));
SHOW
CREATE
TABLE
t1
;
INSERT
INTO
t1
VALUES
(
1
,
1
);
SELECT
HEX
(
a
),
HEX
(
b
)
FROM
t1
;
DROP
TABLE
t1
;
--
echo
# 0x00 in the beginning of the second (and following) value of the *last* ENUM/SET in the table:
CREATE
TABLE
t1
(
a
ENUM
(
'a'
,
0x0061
));
SHOW
CREATE
TABLE
t1
;
INSERT
INTO
t1
VALUES
(
1
),(
2
);
SELECT
HEX
(
a
)
FROM
t1
ORDER
BY
a
;
DROP
TABLE
t1
;
CREATE
TABLE
t1
(
a
ENUM
(
'a'
),
b
ENUM
(
'b'
,
0x0061
));
SHOW
CREATE
TABLE
t1
;
INSERT
INTO
t1
VALUES
(
1
,
1
);
INSERT
INTO
t1
VALUES
(
1
,
2
);
SELECT
HEX
(
a
),
HEX
(
b
)
FROM
t1
ORDER
BY
a
,
b
;
DROP
TABLE
t1
;
--
echo
0x00
in
the
beginning
of
a
value
of
a
non
-
last
ENUM
/
SET
causes
an
error
:
--
replace_regex
/
'.*t1.frm'
/
'DIR\/t1.frm'
/
--
error
ER_NOT_FORM_FILE
CREATE
TABLE
t1
(
a
ENUM
(
'a'
,
0x0061
),
b
ENUM
(
'b'
));
--
echo
#
--
echo
# End of 10.1 tests
--
echo
#
sql/table.cc
View file @
bdab5b66
...
...
@@ -76,8 +76,11 @@ static int64 last_table_id;
/* Functions defined in this file */
static
void
fix_type_pointers
(
const
char
***
array
,
TYPELIB
*
point_to_type
,
uint
types
,
char
**
names
);
static
bool
fix_type_pointers
(
const
char
***
typelib_value_names
,
uint
**
typelib_value_lengths
,
TYPELIB
*
point_to_type
,
uint
types
,
char
*
names
,
size_t
names_length
);
static
uint
find_field
(
Field
**
fields
,
uchar
*
record
,
uint
start
,
uint
length
);
inline
bool
is_system_table_name
(
const
char
*
name
,
uint
length
);
...
...
@@ -694,7 +697,8 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end,
uint
keys
,
KEY
*
keyinfo
,
uint
new_frm_ver
,
uint
&
ext_key_parts
,
TABLE_SHARE
*
share
,
uint
len
,
KEY
*
first_keyinfo
,
char
*
&
keynames
)
KEY
*
first_keyinfo
,
LEX_STRING
*
keynames
)
{
uint
i
,
j
,
n_length
;
KEY_PART_INFO
*
key_part
=
NULL
;
...
...
@@ -837,10 +841,13 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end,
}
share
->
ext_key_parts
+=
keyinfo
->
ext_key_parts
;
}
keynames
=
(
char
*
)
key_part
;
strpos
+=
strnmov
(
keynames
,
(
char
*
)
strpos
,
frm_image_end
-
strpos
)
-
keynames
;
keynames
->
str
=
(
char
*
)
key_part
;
keynames
->
length
=
strnmov
(
keynames
->
str
,
(
char
*
)
strpos
,
frm_image_end
-
strpos
)
-
keynames
->
str
;
strpos
+=
keynames
->
length
;
if
(
*
strpos
++
)
// key names are \0-terminated
return
1
;
keynames
->
length
++
;
// Include '\0', to make fix_type_pointers() happy.
//reading index comments
for
(
keyinfo
=
share
->
key_info
,
i
=
0
;
i
<
keys
;
i
++
,
keyinfo
++
)
...
...
@@ -1178,11 +1185,13 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
TABLE_SHARE
*
share
=
this
;
uint
new_frm_ver
,
field_pack_length
,
new_field_pack_flag
;
uint
interval_count
,
interval_parts
,
read_length
,
int_length
;
uint
total_typelib_value_count
;
uint
db_create_options
,
keys
,
key_parts
,
n_length
;
uint
com_length
,
null_bit_pos
,
UNINIT_VAR
(
mysql57_vcol_null_bit_pos
),
bitmap_count
;
uint
i
;
bool
use_hash
,
mysql57_null_bits
=
0
;
char
*
keynames
,
*
names
,
*
comment_pos
;
LEX_STRING
keynames
=
{
NULL
,
0
};
char
*
names
,
*
comment_pos
;
const
uchar
*
forminfo
,
*
extra2
;
const
uchar
*
frm_image_end
=
frm_image
+
frm_length
;
uchar
*
record
,
*
null_flags
,
*
null_pos
,
*
UNINIT_VAR
(
mysql57_vcol_null_pos
);
...
...
@@ -1194,6 +1203,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
KEY_PART_INFO
*
key_part
=
NULL
;
Field
**
field_ptr
,
*
reg_field
;
const
char
**
interval_array
;
uint
*
typelib_value_lengths
=
NULL
;
enum
legacy_db_type
legacy_db_type
;
my_bitmap_map
*
bitmaps
;
bool
null_bits_are_used
;
...
...
@@ -1496,7 +1506,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if
(
create_key_infos
(
disk_buff
+
6
,
frm_image_end
,
keys
,
keyinfo
,
new_frm_ver
,
ext_key_parts
,
share
,
len
,
&
first_keyinfo
,
keynames
))
share
,
len
,
&
first_keyinfo
,
&
keynames
))
goto
err
;
if
(
next_chunk
+
5
<
buff_end
)
...
...
@@ -1589,7 +1599,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
{
if
(
create_key_infos
(
disk_buff
+
6
,
frm_image_end
,
keys
,
keyinfo
,
new_frm_ver
,
ext_key_parts
,
share
,
len
,
&
first_keyinfo
,
keynames
))
share
,
len
,
&
first_keyinfo
,
&
keynames
))
goto
err
;
}
...
...
@@ -1630,11 +1640,34 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
DBUG_PRINT
(
"info"
,(
"i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d vcol_screen_length: %d"
,
interval_count
,
interval_parts
,
keys
,
n_length
,
int_length
,
com_length
,
vcol_screen_length
));
/*
We load the following things into TYPELIBs:
- One TYPELIB for field names
- interval_count TYPELIBs for ENUM/SET values
- One TYPELIB for key names
Every TYPELIB requires one extra value with a NULL pointer and zero length,
which is the end-of-values marker.
TODO-10.5+:
Note, we should eventually reuse this total_typelib_value_count
to allocate interval_array. The below code reserves less space
than total_typelib_value_count pointers. So it seems `interval_array`
and `names` overlap in the memory. Too dangerous to fix in 10.1.
*/
total_typelib_value_count
=
(
share
->
fields
+
1
/*end-of-values marker*/
)
+
(
interval_parts
+
interval_count
/*end-of-values markers*/
)
+
(
keys
+
1
/*end-of-values marker*/
);
if
(
!
multi_alloc_root
(
&
share
->
mem_root
,
&
share
->
field
,
(
uint
)(
share
->
fields
+
1
)
*
sizeof
(
Field
*
),
&
share
->
intervals
,
(
uint
)
interval_count
*
sizeof
(
TYPELIB
),
&
share
->
check_constraints
,
(
uint
)
share
->
table_check_constraints
*
sizeof
(
Virtual_column_info
*
),
/*
This looks wrong: shouldn't it be (+2+interval_count)
instread of (+3) ?
*/
&
interval_array
,
(
uint
)
(
share
->
fields
+
interval_parts
+
keys
+
3
)
*
sizeof
(
char
*
),
&
typelib_value_lengths
,
total_typelib_value_count
*
sizeof
(
uint
*
),
&
names
,
(
uint
)
(
n_length
+
int_length
),
&
comment_pos
,
(
uint
)
com_length
,
&
vcol_screen_pos
,
vcol_screen_length
,
...
...
@@ -1661,33 +1694,21 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
memcpy
(
vcol_screen_pos
,
disk_buff
+
read_length
-
vcol_screen_length
,
vcol_screen_length
);
fix_type_pointers
(
&
interval_array
,
&
share
->
fieldnames
,
1
,
&
names
);
if
(
share
->
fieldnames
.
count
!=
share
->
fields
)
if
(
fix_type_pointers
(
&
interval_array
,
&
typelib_value_lengths
,
&
share
->
fieldnames
,
1
,
names
,
n_length
)
||
share
->
fieldnames
.
count
!=
share
->
fields
)
goto
err
;
fix_type_pointers
(
&
interval_array
,
share
->
intervals
,
interval_count
,
&
names
);
{
/* Set ENUM and SET lengths */
TYPELIB
*
interval
;
for
(
interval
=
share
->
intervals
;
interval
<
share
->
intervals
+
interval_count
;
interval
++
)
{
uint
count
=
(
uint
)
(
interval
->
count
+
1
)
*
sizeof
(
uint
);
if
(
!
(
interval
->
type_lengths
=
(
uint
*
)
alloc_root
(
&
share
->
mem_root
,
count
)))
if
(
fix_type_pointers
(
&
interval_array
,
&
typelib_value_lengths
,
share
->
intervals
,
interval_count
,
names
+
n_length
,
int_length
))
goto
err
;
for
(
count
=
0
;
count
<
interval
->
count
;
count
++
)
{
char
*
val
=
(
char
*
)
interval
->
type_names
[
count
];
interval
->
type_lengths
[
count
]
=
strlen
(
val
);
}
interval
->
type_lengths
[
count
]
=
0
;
}
}
if
(
keynames
)
fix_type_pointers
(
&
interval_array
,
&
share
->
keynames
,
1
,
&
keynames
);
if
(
keynames
.
length
&&
(
fix_type_pointers
(
&
interval_array
,
&
typelib_value_lengths
,
&
share
->
keynames
,
1
,
keynames
.
str
,
keynames
.
length
)
||
share
->
keynames
.
count
!=
keys
))
goto
err
;
/* Allocate handler */
if
(
!
(
handler_file
=
get_new_handler
(
share
,
thd
->
mem_root
,
...
...
@@ -3622,37 +3643,81 @@ void open_table_error(TABLE_SHARE *share, enum open_frm_error error,
** with a '\0'
*/
static
void
fix_type_pointers
(
const
char
***
array
,
TYPELIB
*
point_to_type
,
uint
types
,
char
**
names
)
static
bool
fix_type_pointers
(
const
char
***
typelib_value_names
,
uint
**
typelib_value_lengths
,
TYPELIB
*
point_to_type
,
uint
types
,
char
*
ptr
,
size_t
length
)
{
char
*
type_name
,
*
ptr
;
char
chr
;
const
char
*
end
=
ptr
+
length
;
ptr
=
*
names
;
while
(
types
--
)
{
char
sep
;
point_to_type
->
name
=
0
;
point_to_type
->
type_names
=
*
array
;
point_to_type
->
type_names
=
*
typelib_value_names
;
point_to_type
->
type_lengths
=
*
typelib_value_lengths
;
if
((
chr
=
*
ptr
))
/* Test if empty type */
/*
Typelib can be encoded as:
1) 0x00 - empty typelib
2) 0xFF 0x00 - empty typelib (index names)
3) sep (value sep)... 0x00 - non-empty typelib (where sep is a separator)
*/
if
(
length
==
2
&&
ptr
[
0
]
==
(
char
)
0xFF
&&
ptr
[
1
]
==
'\0'
)
{
while
((
type_name
=
strchr
(
ptr
+
1
,
chr
))
!=
NullS
)
/*
This is a special case #2.
If there are no indexes at all, index names can be encoded
as a two byte sequence: 0xFF 0x00
TODO: Check if it's a bug in the FRM packing routine.
It should probably write just 0x00 instead of 0xFF00.
*/
ptr
+=
2
;
}
else
if
((
sep
=
*
ptr
++
))
// A non-empty typelib
{
*
((
*
array
)
++
)
=
ptr
+
1
;
*
type_name
=
'\0'
;
/* End string */
ptr
=
type_name
;
for
(
;
ptr
<
end
;
)
{
// Now scan the next value+sep pair
char
*
vend
=
(
char
*
)
memchr
(
ptr
,
sep
,
end
-
ptr
);
if
(
!
vend
)
return
true
;
// Bad format
*
((
*
typelib_value_names
)
++
)
=
ptr
;
*
((
*
typelib_value_lengths
)
++
)
=
vend
-
ptr
;
*
vend
=
'\0'
;
// Change sep to '\0'
ptr
=
vend
+
1
;
// Shift from sep to the next byte
/*
Now we can have either:
- the end-of-typelib marker (0x00)
- more value+sep pairs
*/
if
(
!*
ptr
)
{
/*
We have an ambiguity here. 0x00 can be an end-of-typelib marker,
but it can also be a part of the next value:
CREATE TABLE t1 (a ENUM(0x61, 0x0062) CHARACTER SET BINARY);
If this is the last ENUM/SET in the table and there is still more
packed data left after 0x00, then we know for sure that 0x00
is a part of the next value.
TODO-10.5+: we should eventually introduce a new unambiguous
typelib encoding for FRM.
*/
if
(
!
types
&&
ptr
+
1
<
end
)
continue
;
// A binary value starting with 0x00
ptr
++
;
// Consume the end-of-typelib marker
break
;
// End of the current typelib
}
ptr
+=
2
;
/* Skip end mark and last 0 */
}
else
ptr
++
;
point_to_type
->
count
=
(
uint
)
(
*
array
-
point_to_type
->
type_names
);
}
point_to_type
->
count
=
(
uint
)
(
*
typelib_value_names
-
point_to_type
->
type_names
);
point_to_type
++
;
*
((
*
array
)
++
)
=
NullS
;
/* End of type */
*
((
*
typelib_value_names
)
++
)
=
NullS
;
/* End of type */
*
((
*
typelib_value_lengths
)
++
)
=
0
;
/* End of type */
}
*
names
=
ptr
;
/* Update end */
return
;
return
ptr
!=
end
;
}
/* fix_type_pointers */
...
...
sql/unireg.cc
View file @
bdab5b66
...
...
@@ -594,6 +594,18 @@ static bool pack_vcols(String *buf, List<Create_field> &create_fields,
}
static
uint
typelib_values_packed_length
(
const
TYPELIB
*
t
)
{
uint
length
=
0
;
for
(
uint
i
=
0
;
t
->
type_names
[
i
];
i
++
)
{
length
+=
t
->
type_lengths
[
i
];
length
++
;
/* Separator */
}
return
length
;
}
/* Make formheader */
static
bool
pack_header
(
THD
*
thd
,
uchar
*
forminfo
,
...
...
@@ -686,9 +698,8 @@ static bool pack_header(THD *thd, uchar *forminfo,
field
->
interval_id
=
get_interval_id
(
&
int_count
,
create_fields
,
field
);
if
(
old_int_count
!=
int_count
)
{
for
(
const
char
**
pos
=
field
->
interval
->
type_names
;
*
pos
;
pos
++
)
int_length
+=
(
uint
)
strlen
(
*
pos
)
+
1
;
// field + suffix prefix
int_parts
+=
field
->
interval
->
count
+
1
;
int_length
+=
typelib_values_packed_length
(
field
->
interval
);
int_parts
+=
field
->
interval
->
count
+
1
;
}
}
if
(
f_maybe_null
(
field
->
pack_flag
))
...
...
@@ -777,11 +788,7 @@ static size_t packed_fields_length(List<Create_field> &create_fields)
{
int_count
=
field
->
interval_id
;
length
++
;
for
(
int
i
=
0
;
field
->
interval
->
type_names
[
i
];
i
++
)
{
length
+=
field
->
interval
->
type_lengths
[
i
];
length
++
;
}
length
+=
typelib_values_packed_length
(
field
->
interval
);
length
++
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment