1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-07 00:04:31 +03:00

MDEV-27743 Remove Lex::charset

This patch also fixes:

MDEV-27690 Crash on `CHARACTER SET csname COLLATE DEFAULT` in column definition
MDEV-27853 Wrong data type on column `COLLATE DEFAULT` and table `COLLATE some_non_default_collation`
MDEV-28067 Multiple conflicting column COLLATE clauses are not rejected
MDEV-28118 Wrong collation of `CAST(.. AS CHAR COLLATE DEFAULT)`
MDEV-28119 Wrong column collation on MODIFY + CONVERT
This commit is contained in:
Alexander Barkov
2022-02-09 21:21:39 +04:00
parent d25b10fede
commit 0c4c064f98
34 changed files with 13752 additions and 242 deletions

View File

@@ -3693,7 +3693,10 @@ static char *fieldflags2str(uint f) {
ff2s_check_flag(NUM); ff2s_check_flag(NUM);
ff2s_check_flag(PART_KEY); ff2s_check_flag(PART_KEY);
ff2s_check_flag(GROUP); ff2s_check_flag(GROUP);
ff2s_check_flag(BINCMP); /*
CONTEXT_COLLATION_FLAG (former BINCMP_FLAG) is used at parse
time only and should never show up on the client side. Don't test it.
*/
ff2s_check_flag(ON_UPDATE_NOW); ff2s_check_flag(ON_UPDATE_NOW);
#undef ff2s_check_flag #undef ff2s_check_flag
if (f) if (f)

View File

@@ -1269,6 +1269,15 @@ extern struct charset_info_st my_charset_utf8mb4_general_nopad_ci;
extern struct charset_info_st my_charset_utf8mb4_unicode_ci; extern struct charset_info_st my_charset_utf8mb4_unicode_ci;
extern struct charset_info_st my_charset_utf8mb4_unicode_nopad_ci; extern struct charset_info_st my_charset_utf8mb4_unicode_nopad_ci;
/*
Contextually typed collations, e.g.:
CHAR(10) COLLATE DEFAULT
CHAR(10) BINARY
*/
extern struct charset_info_st my_collation_contextually_typed_default;
extern struct charset_info_st my_collation_contextually_typed_binary;
#define MY_UTF8MB3 "utf8mb3" #define MY_UTF8MB3 "utf8mb3"
#define MY_UTF8MB4 "utf8mb4" #define MY_UTF8MB4 "utf8mb4"

View File

@@ -180,7 +180,7 @@ enum enum_indicator_type
#define NUM_FLAG 32768U /* Field is num (for clients) */ #define NUM_FLAG 32768U /* Field is num (for clients) */
#define PART_KEY_FLAG 16384U /* Intern; Part of some key */ #define PART_KEY_FLAG 16384U /* Intern; Part of some key */
#define GROUP_FLAG 32768U /* Intern: Group field */ #define GROUP_FLAG 32768U /* Intern: Group field */
#define BINCMP_FLAG 131072U /* Intern: Used by sql_yacc */ #define CONTEXT_COLLATION_FLAG 131072U /* Intern: Used by sql_yacc */
#define GET_FIXED_FIELDS_FLAG (1U << 18) /* Used to get fields in item tree */ #define GET_FIXED_FIELDS_FLAG (1U << 18) /* Used to get fields in item tree */
#define FIELD_IN_PART_FUNC_FLAG (1U << 19)/* Field part of partition func */ #define FIELD_IN_PART_FUNC_FLAG (1U << 19)/* Field part of partition func */
#define PART_INDIRECT_KEY_FLAG (1U << 20) #define PART_INDIRECT_KEY_FLAG (1U << 20)

View File

@@ -118,6 +118,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/sql_analyze_stmt.cc ../sql/sql_analyze_stmt.h ../sql/sql_analyze_stmt.cc ../sql/sql_analyze_stmt.h
../sql/compat56.cc ../sql/compat56.cc
../sql/sql_schema.cc ../sql/sql_schema.cc
../sql/lex_charset.cc
../sql/sql_type.cc ../sql/sql_type.h ../sql/sql_type.cc ../sql/sql_type.h
../sql/sql_mode.cc ../sql/sql_mode.cc
../sql/sql_type_string.cc ../sql/sql_type_string.cc

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,627 @@
--source include/have_utf8mb4.inc
--echo #
--echo # Start of 10.9 tests
--echo #
--echo #
--echo # MDEV-27853 Wrong data type on column `COLLATE DEFAULT` and table `COLLATE some_non_default_collation`
--echo #
CREATE TABLE t1 (
a CHAR(10) COLLATE DEFAULT
) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # MDEV-28067 Multiple conflicting column COLLATE clauses are not rejected
--echo #
--error ER_CONFLICTING_DECLARATIONS
CREATE TABLE t1 (a CHAR(10) COLLATE latin1_swedish_ci NOT NULL COLLATE latin1_bin);
--error ER_CONFLICTING_DECLARATIONS
CREATE TABLE t1 (a CHAR(10) COLLATE DEFAULT NOT NULL COLLATE latin1_bin);
--error ER_CONFLICTING_DECLARATIONS
CREATE TABLE t1 (a CHAR(10) BINARY NOT NULL COLLATE latin1_swedish_ci);
CREATE TABLE t1 (a CHAR(10) COLLATE DEFAULT NOT NULL COLLATE latin1_swedish_ci);
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(10) BINARY NOT NULL COLLATE latin1_bin);
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # MDEV-27743 Remove Lex::charset
--echo #
# Iterate through all possible combinations of this grammar:
#
# CREATE TABLE t1 (
# a CHAR(10) [ CHARACTER SET cs ] [ COLLATE cl0 | BINARY ]
# NOT NULL [COLLATE cl1]
# DEFAULT '' [COLLATE cl2]
# ) [CHARACTER SET tcs [COLLATE tcl]];
#
# and check that:
# - either the column gets the expected character set and collation
# - or the expected error is returned
CREATE TABLE cs (cs VARCHAR(64) NOT NULL);
INSERT INTO cs (cs) VALUES
(''),
('CHARACTER SET latin1'),
('CHARACTER SET utf8mb4');
CREATE TABLE cl0 (cl0 VARCHAR(64) NOT NULL);
INSERT INTO cl0 (cl0) VALUES
(''),
('BINARY'),
('COLLATE DEFAULT'),
('COLLATE latin1_bin'),
('COLLATE latin1_swedish_ci'),
('COLLATE utf8mb4_bin'),
('COLLATE utf8mb4_general_ci');
CREATE TABLE cl1 (cl1 VARCHAR(64) NOT NULL);
INSERT INTO cl1 (cl1) VALUES
(''),
('COLLATE DEFAULT'),
('COLLATE latin1_bin'),
('COLLATE latin1_swedish_ci'),
('COLLATE utf8mb4_bin'),
('COLLATE utf8mb4_general_ci');
CREATE TABLE tcs (tcs VARCHAR(64) NOT NULL);
INSERT INTO tcs (tcs) VALUES
(''),
('CHARACTER SET latin1'),
('CHARACTER SET latin1 COLLATE latin1_bin'),
('CHARACTER SET utf8mb4'),
('CHARACTER SET utf8mb4 COLLATE utf8mb4_bin');
CREATE FUNCTION is_collate_clause_with_explicit_default_collation(cl VARCHAR(64))
RETURNS BOOLEAN
RETURN cl IN
('COLLATE latin1_swedish_ci',
'COLLATE utf8mb4_general_ci'
);
CREATE FUNCTION is_collate_clause_with_explicit_collation(cl VARCHAR(64))
RETURNS BOOLEAN
RETURN cl IN
('COLLATE latin1_swedish_ci',
'COLLATE latin1_bin',
'COLLATE utf8mb4_general_ci',
'COLLATE utf8mb4_bin'
);
CREATE FUNCTION is_conflicting_collate_explicit2(result TEXT,
a VARCHAR(64),
b VARCHAR(64))
RETURNS BOOLEAN
RETURN a<>b
AND is_collate_clause_with_explicit_collation(a)
AND is_collate_clause_with_explicit_collation(b)
AND result LIKE 'ERROR%HY000%Conflicting declarations%';
CREATE FUNCTION is_conflicting_collate_default_collate_explicit(result TEXT,
b VARCHAR(64))
RETURNS BOOLEAN
RETURN is_collate_clause_with_explicit_collation(b)
AND NOT is_collate_clause_with_explicit_default_collation(b)
AND result LIKE 'ERROR%HY000%Conflicting declarations%';
CREATE FUNCTION
is_conflicting_charset_explicit_collate_explicit(result TEXT,
cs_clause VARCHAR(64),
cl_clause VARCHAR(64))
RETURNS BOOLEAN
RETURN cs_clause LIKE 'CHARACTER SET%'
AND is_collate_clause_with_explicit_collation(cl_clause)
AND REGEXP_SUBSTR(cs_clause,'[0-9a-z_]*$') <>
REGEXP_SUBSTR(cl_clause,'(?<=COLLATE )[0-9a-z_]*')
AND result LIKE 'ERROR%42000%COLLATION%is not valid for CHARACTER SET%';
CREATE FUNCTION collate_cs_default_collation(cs_name VARCHAR(64))
RETURNS VARCHAR(64)
RETURN
(SELECT CONCAT('COLLATE ',COLLATION_NAME)
FROM INFORMATION_SCHEMA.COLLATIONS
WHERE IS_DEFAULT='Yes' AND CHARACTER_SET_NAME = cs_name);
CREATE TABLE results
(
dt VARCHAR(64),
cs VARCHAR(64),
cl0 VARCHAR(64),
cl1 VARCHAR(64),
cl2 VARCHAR(64),
tcs VARCHAR(64),
query VARCHAR(1024),
result VARCHAR(1024),
cs_name VARCHAR(64) GENERATED ALWAYS AS
(CASE WHEN cs LIKE 'CHARACTER SET%' THEN REGEXP_SUBSTR(cs,'[0-9a-z_]*$')
ELSE NULL
END
),
collate_cs_bin VARCHAR(64) GENERATED ALWAYS AS
(
CONCAT('COLLATE ', cs_name, '_bin')
),
tcs_character_set_name VARCHAR(64) GENERATED ALWAYS AS
(CASE WHEN tcs LIKE 'CHARACTER SET%' THEN REGEXP_SUBSTR(tcs,'(?<=CHARACTER SET )[0-9a-z]*')
ELSE NULL
END
)
);
DELIMITER $$;
CREATE PROCEDURE p1(dt TEXT, cs TEXT, cl0 TEXT, cl1 TEXT, cl2 TEXT, tcs TEXT)
BEGIN
DECLARE errstate TEXT DEFAULT NULL;
DECLARE errno INT DEFAULT NULL;
DECLARE errmsg TEXT DEFAULT NULL;
DECLARE query TEXT;
DECLARE result TEXT;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 errstate = RETURNED_SQLSTATE,
errno = MYSQL_ERRNO, errmsg = MESSAGE_TEXT;
END;
SET query= CONCAT('CREATE TABLE t1 (a ', dt, ' ', cs, ' ', cl0,
' NOT NULL ',cl1,
' DEFAULT '''' ', cl2,
') ', tcs, ' ENGINE=Memory');
EXECUTE IMMEDIATE query;
IF errmsg IS NOT NULL
THEN
SET result=CONCAT('ERROR: ',
COALESCE(errstate,'<NULL>'), ' ',
COALESCE(errno,'<NULL>'), ' ',
COALESCE(errmsg,'<NULL>'));
INSERT INTO results (dt,cs,cl0,cl1,cl2,tcs,query,result)
VALUES (dt,cs,cl0,cl1,cl2,tcs,query,result);
ELSE
FOR row IN (SELECT CONCAT(COLUMN_TYPE,
' CHARACTER SET ', CHARACTER_SET_NAME,
' COLLATE ', COLLATION_NAME) AS result
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1')
DO
INSERT INTO results (dt,cs,cl0,cl1,cl2,tcs,query,result)
VALUES (dt,cs,cl0,cl1,cl2,tcs,query,row.result);
END FOR;
DROP TABLE t1;
END IF;
END;
$$
DELIMITER ;$$
DELIMITER $$;
CREATE PROCEDURE p3(dt TEXT)
BEGIN
FOR row IN (
SELECT cs, cl0, cl1.cl1 AS cl1, cl2.cl1 AS cl2, tcs
FROM cs, cl0, cl1, cl1 AS cl2, tcs
ORDER BY cs, cl0, cl1, cl2, tcs
)
DO
CALL p1(dt, row.cs, row.cl0, row.cl1, row.cl2, row.tcs);
END FOR;
END;
$$
DELIMITER ;$$
--disable_column_names
CALL p3('char(10)');
--enable_column_names
--vertical_results
SELECT query, result, '' AS `` FROM results
ORDER BY dt, cs, cl0, cl1, cl2, tcs;
--horizontal_results
DROP PROCEDURE p1;
DROP PROCEDURE p3;
DROP TABLE cs, cl0, cl1, tcs;
#
# Statements with errors
#
#
# CHARACTER SET cs2 COLLATE cs2_xxx
# CHARACTER SET cs1 NOT NULL COLLATE cs2_xxx DEFAULT '' [COLLATE cs2_xxx]
# CHARACTER SET cs1 NOT NULL DEFAULT '' COLLATE cs2_xxx
#
DELETE FROM results
WHERE is_conflicting_charset_explicit_collate_explicit(result, cs, cl0);
SELECT ROW_COUNT();
DELETE FROM results
WHERE cl0=''
AND cl2=''
AND is_conflicting_charset_explicit_collate_explicit(result, cs, cl1);
SELECT ROW_COUNT();
DELETE FROM results
WHERE cl0=''
AND (cl1='' OR cl1=cl2)
AND is_conflicting_charset_explicit_collate_explicit(result, cs, cl2);
SELECT ROW_COUNT();
# CHARACTER SET cs COLLATE DEFAULT
# NOT NULL [COLLATE cs_non_default]
# DEFAULT '' [COLLATE cs_non_default]
DELETE FROM results
WHERE cs LIKE 'CHARACTER SET%'
AND cl0='COLLATE DEFAULT'
AND cl2=''
AND is_conflicting_collate_explicit2(result, collate_cs_default_collation(cs_name), cl1);
SELECT ROW_COUNT();
DELETE FROM results
WHERE cs LIKE 'CHARACTER SET%'
AND cl0='COLLATE DEFAULT'
AND (cl1=''||cl2=cl1)
AND is_conflicting_collate_explicit2(result, collate_cs_default_collation(cs_name), cl2);
SELECT ROW_COUNT();
#
# `COLLATE DEFAULT` is not supported in cl1 and cl2
#
DELETE FROM results
WHERE (cl1='COLLATE DEFAULT' OR cl2='COLLATE DEFAULT')
AND result LIKE 'ERROR%42000%syntax%near%DEFAULT%';
SELECT ROW_COUNT();
#
# Conflicting COLLATE with explicit collation name
#
DELETE FROM results WHERE is_conflicting_collate_explicit2(result, cl1, cl2);
SELECT ROW_COUNT();
DELETE FROM results
WHERE cl2='' AND is_conflicting_collate_explicit2(result, cl0, cl1);
SELECT ROW_COUNT();
DELETE FROM results
WHERE (cl1='' OR cl1=cl2) AND is_conflicting_collate_explicit2(result, cl0, cl2);
SELECT ROW_COUNT();
#
# CHAR(10) COLLATE DEFAULT .. COLLATE cs_non_default
#
DELETE FROM results
WHERE cs='' AND cl0='COLLATE DEFAULT'
AND
((cl1='' AND is_conflicting_collate_default_collate_explicit(result, cl2)) OR
(cl2='' AND is_conflicting_collate_default_collate_explicit(result, cl1)) OR
(cl2=cl1 AND is_conflicting_collate_default_collate_explicit(result, cl1)));
SELECT ROW_COUNT();
#
# CHAR(10) BINARY .. COLLATE xxx_ci
#
DELETE FROM results
WHERE cl0 LIKE 'BINARY' AND
((cl1='' AND cl2 NOT LIKE '%_bin' AND is_collate_clause_with_explicit_collation(cl2)) OR
(cl2='' AND cl1 NOT LIKE '%_bin' AND is_collate_clause_with_explicit_collation(cl1)) OR
(cl1=cl2 AND cl1 NOT LIKE '%_bin' AND is_collate_clause_with_explicit_collation(cl1)))
AND result LIKE 'ERROR%HY000%Conflicting declarations%';
SELECT ROW_COUNT();
#
# CHAR(10) CHARACTER SET cs1 BINARY .. COLLATE cs2_..
#
DELETE FROM results
WHERE cs LIKE 'CHARACTER SET%' AND cl0='BINARY'
AND cl1=''
AND is_collate_clause_with_explicit_collation(cl2)
AND cl2 NOT LIKE CONCAT(cs_name, '%')
AND result LIKE 'ERROR%HY000%Conflicting declarations%';
SELECT ROW_COUNT();
DELETE FROM results
WHERE cs LIKE 'CHARACTER SET%' AND cl0='BINARY'
AND (cl2='' || cl2=cl1)
AND is_collate_clause_with_explicit_collation(cl1)
AND cl1 NOT LIKE CONCAT(cs_name, '%')
AND result LIKE 'ERROR%HY000%Conflicting declarations%';
SELECT ROW_COUNT();
#
# Statements without errors
# where the character set and the collation are determined from
# the database level.
#
# CREATE TABLE t1 (a CHAR(10) [COLLATE DEFAULT] NOT NULL DEFAULT '');
DELETE FROM results
WHERE cs='' AND cl0 IN ('','COLLATE DEFAULT')
AND cl1='' AND cl2='' AND tcs=''
AND result NOT LIKE 'ERROR%'
AND result RLIKE
(SELECT CONCAT('CHARACTER SET ', DEFAULT_CHARACTER_SET_NAME, ' ',
'COLLATE ', DEFAULT_COLLATION_NAME)
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME=database()
);
SELECT ROW_COUNT();
# CREATE TABLE t1 (a CHAR(10) BINARY NOT NULL DEFAULT '');
DELETE FROM results
WHERE cs='' AND cl0='BINARY' AND cl1='' AND cl2='' AND tcs=''
AND result NOT LIKE 'ERROR%'
AND result RLIKE
(SELECT CONCAT('CHARACTER SET ', DEFAULT_CHARACTER_SET_NAME, ' ',
'COLLATE ', DEFAULT_CHARACTER_SET_NAME, '_bin')
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME=database()
);
SELECT ROW_COUNT();
#
# Statements without errors
# where the character set and the collation are determined from
# the table level.
#
# CREATE TABLE t1 (a char(10) NOT NULL DEFAULT '') CHARACTER SET cs
DELETE FROM results
WHERE cs=''
AND cl0=''
AND cl1=''
AND cl2=''
AND tcs LIKE 'CHARACTER SET%'
AND tcs NOT LIKE '%COLLATE%'
AND result NOT LIKE 'ERROR%'
AND result RLIKE tcs
AND result RLIKE collate_cs_default_collation(tcs_character_set_name);
SELECT ROW_COUNT();
#
# CREATE TABLE t1 (a CHAR(10) NOT NULL DEFAULT '') CHARACTER SET cs COLLATE cs_xxx
#
DELETE FROM results
WHERE cs='' AND cl0='' AND cl1='' AND cl2=''
AND tcs LIKE 'CHARACTER SET%COLLATE%'
AND result NOT LIKE 'ERROR%'
AND result RLIKE tcs;
SELECT ROW_COUNT();
#
# CREATE TABLE t1 (a CHAR(10) COLLATE DEFAULT) CHARACTER SET cs ..
#
DELETE FROM results
WHERE cs=''
AND cl0='COLLATE DEFAULT'
AND cl1=''
AND cl2=''
AND tcs LIKE 'CHARACTER SET%'
AND result NOT LIKE 'ERROR%'
AND result RLIKE collate_cs_default_collation(tcs_character_set_name);
SELECT ROW_COUNT();
# CREATE TABLE t1
# (
# a CHAR(10) BINARY NOT NULL DEFAULT ''
# ) CHARACTER SET cs COLLATE cs_bin;
DELETE FROM results
WHERE cs=''
AND cl0='BINARY'
AND cl1=''
AND cl2=''
AND tcs LIKE 'CHARACTER SET%'
AND result NOT LIKE 'ERROR%'
AND result RLIKE CONCAT('COLLATE ', tcs_character_set_name, '_bin');
SELECT ROW_COUNT();
#
# Statements without errors
# where the character set and the collation are determined from
# the column level.
#
#
# CHAR(10) COLLATE cs_xxx .. [COLLATE cs_xxx] .. [COLLATE cs_xxx]
#
DELETE FROM results
WHERE cs='' AND is_collate_clause_with_explicit_collation(cl0)
AND (cl1='' OR cl1=cl0)
AND (cl2='' OR cl2=cl0)
AND result NOT LIKE 'ERROR%'
AND result RLIKE cl0;
SELECT ROW_COUNT();
#
# CHARACTER SET cs [COLLATE DEFAULT|COLLATE cs_def]
# NOT NULL [COLLATE cs_def]
# DEFAULT '' [COLLATE cs_def]
DELETE FROM results
WHERE cs LIKE 'CHARACTER SET %'
AND cl0 IN ('','COLLATE DEFAULT',collate_cs_default_collation(cs_name))
AND cl1 IN ('',collate_cs_default_collation(cs_name))
AND cl2 IN ('',collate_cs_default_collation(cs_name))
AND result NOT LIKE 'ERROR%'
AND result RLIKE collate_cs_default_collation(cs_name);
SELECT ROW_COUNT();
#
# CHAR(10) COLLATE DEFAULT .. COLLATE cs_def .. [COLLATE cs_def]
#
DELETE FROM results
WHERE cs=''
AND cl0='COLLATE DEFAULT'
AND is_collate_clause_with_explicit_default_collation(cl1)
AND cl2=''
AND result NOT LIKE 'ERROR%'
AND result RLIKE cl1;
SELECT ROW_COUNT();
#
# CHAR(10) COLLATE DEFAULT .. COLLATE cs_def .. [COLLATE cs_def]
#
DELETE FROM results
WHERE cs=''
AND cl0='COLLATE DEFAULT'
AND is_collate_clause_with_explicit_default_collation(cl2)
AND (cl1='' OR cl2=cl1)
AND result NOT LIKE 'ERROR%'
AND result RLIKE cl2;
SELECT ROW_COUNT();
#
# CHARACTER SET cs [BINARY|COLLATE cs_bin]
# NOT NULL [COLLATE cs_bin]
# DEFAULT '' [COLLATE cs_bin]
DELETE FROM results
WHERE cs LIKE 'CHARACTER SET %'
AND (cl0='BINARY' OR cl0=collate_cs_bin)
AND (cl1='' OR cl1=collate_cs_bin)
AND (cl2='' OR cl2=collate_cs_bin)
AND result NOT LIKE 'ERROR%'
AND result RLIKE collate_cs_bin;
SELECT ROW_COUNT();
#
# CHARACTER SET cs NOT NULL DEFAULT '' COLLATE cs_def
# CHARACTER SET cs NOT NULL COLLATE cs_def DEFAULT '' [COLLATE cs_def]
#
DELETE FROM results
WHERE cs LIKE 'CHARACTER SET%' AND cl0=''
AND (cl2='' OR cl2=cl1)
AND is_collate_clause_with_explicit_collation(cl1)
AND cl1 RLIKE CONCAT('COLLATE ',cs_name,'_')
AND result NOT LIKE 'ERROR%'
AND result RLIKE cl1;
SELECT ROW_COUNT();
DELETE FROM results
WHERE cs LIKE 'CHARACTER SET%' AND cl0=''
AND cl1=''
AND is_collate_clause_with_explicit_collation(cl2)
AND cl2 RLIKE CONCAT('COLLATE ',cs_name,'_')
AND result NOT LIKE 'ERROR%'
AND result RLIKE cl2;
SELECT ROW_COUNT();
#
# CHAR(10) BINARY NOT NULL DEFAULT '' COLLATE cs_bin
# CHAR(10) BINARY NOT NULL COLLATE cs_bin DEFAULT '' [COLLATE cs_bin]
#
DELETE FROM results
WHERE cs='' AND cl0='BINARY'
AND (cl2='' OR cl2=cl1)
AND is_collate_clause_with_explicit_collation(cl1)
AND cl1 RLIKE '_bin$'
AND result NOT LIKE 'ERROR%'
AND result RLIKE cl1;
SELECT ROW_COUNT();
DELETE FROM results
WHERE cs='' AND cl0='BINARY'
AND cl1=''
AND is_collate_clause_with_explicit_collation(cl2)
AND cl2 RLIKE '_bin$'
AND result NOT LIKE 'ERROR%'
AND result RLIKE cl2;
SELECT ROW_COUNT();
#
# CHAR(10) NOT NULL DEFAULT '' COLLATE cs_xxx
# CHAR(10) NOT NULL COLLATE cs_xxx DEFAULT '' [COLLATE cs_xxx]
#
DELETE FROM results
WHERE cs='' AND cl0=''
AND cl1=''
AND is_collate_clause_with_explicit_collation(cl2)
AND result NOT LIKE 'ERROR%'
AND result RLIKE cl2;
SELECT ROW_COUNT();
DELETE FROM results
WHERE cs='' AND cl0=''
AND (cl2='' OR cl2=cl1)
AND is_collate_clause_with_explicit_collation(cl1)
AND result NOT LIKE 'ERROR%'
AND result RLIKE cl1;
SELECT ROW_COUNT();
--vertical_results
--echo # Expect empty set
SELECT *, '---' AS `---` FROM results WHERE result LIKE 'ERROR%';
--echo # Expect empty set
SELECT *, '---' AS `---` FROM results WHERE result NOT LIKE 'ERROR%';
--horizontal_results
DROP TABLE results;
DROP FUNCTION is_collate_clause_with_explicit_default_collation;
DROP FUNCTION is_collate_clause_with_explicit_collation;
DROP FUNCTION is_conflicting_charset_explicit_collate_explicit;
DROP FUNCTION is_conflicting_collate_explicit2;
DROP FUNCTION is_conflicting_collate_default_collate_explicit;
DROP FUNCTION collate_cs_default_collation;
--echo #
--echo # End of 10.9 tests
--echo #

View File

@@ -8889,6 +8889,38 @@ a b
111 111 111 111
DROP TABLE t1; DROP TABLE t1;
# #
# MDEV-27690 Crash on `CHARACTER SET csname COLLATE DEFAULT` in column definition
#
CREATE TABLE t1 (a CHAR(10) CHARACTER SET latin1 COLLATE DEFAULT);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SELECT CAST('a' AS CHAR(10) CHARACTER SET latin1 COLLATE DEFAULT);
CAST('a' AS CHAR(10) CHARACTER SET latin1 COLLATE DEFAULT)
a
CREATE TABLE t1 AS
SELECT CAST('a' AS CHAR(10) CHARACTER SET latin1 COLLATE DEFAULT) AS c1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SELECT COLUMN_GET(COLUMN_CREATE(0, 'string'),0 AS CHAR CHARACTER SET latin1 COLLATE DEFAULT) AS c1;
c1
string
CREATE TABLE t1 AS
SELECT COLUMN_GET(COLUMN_CREATE(0, 'string'),0 AS CHAR CHARACTER SET latin1 COLLATE DEFAULT) AS c1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` longtext DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# End of 10.2 tests # End of 10.2 tests
# #
# #
@@ -8950,3 +8982,31 @@ Warning 1292 Truncated incorrect INTEGER value: 'a
# #
# End of 10.5 tests # End of 10.5 tests
# #
#
# Start of 10.6 tests
#
#
# MDEV-27690 Crash on `CHARACTER SET csname COLLATE DEFAULT` in column definition
#
SELECT * FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) CHARACTER SET latin1 COLLATE DEFAULT PATH '$.name'
)
) AS jt;
name
Jeans
CREATE TABLE t1 AS
SELECT * FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) CHARACTER SET latin1 COLLATE DEFAULT PATH '$.name'
)
) AS jt;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`name` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# End of 10.6 tests
#

View File

@@ -438,6 +438,28 @@ let $coll_pad='latin1_bin';
SET NAMES latin1; SET NAMES latin1;
--source include/ctype_like_range_mdev14350.inc --source include/ctype_like_range_mdev14350.inc
--echo #
--echo # MDEV-27690 Crash on `CHARACTER SET csname COLLATE DEFAULT` in column definition
--echo #
CREATE TABLE t1 (a CHAR(10) CHARACTER SET latin1 COLLATE DEFAULT);
SHOW CREATE TABLE t1;
DROP TABLE t1;
SELECT CAST('a' AS CHAR(10) CHARACTER SET latin1 COLLATE DEFAULT);
CREATE TABLE t1 AS
SELECT CAST('a' AS CHAR(10) CHARACTER SET latin1 COLLATE DEFAULT) AS c1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
SELECT COLUMN_GET(COLUMN_CREATE(0, 'string'),0 AS CHAR CHARACTER SET latin1 COLLATE DEFAULT) AS c1;
CREATE TABLE t1 AS
SELECT COLUMN_GET(COLUMN_CREATE(0, 'string'),0 AS CHAR CHARACTER SET latin1 COLLATE DEFAULT) AS c1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo # --echo #
--echo # End of 10.2 tests --echo # End of 10.2 tests
--echo # --echo #
@@ -475,3 +497,29 @@ SELECT CAST(_latin1 0x61FF62 AS INT);
--echo # --echo #
--echo # End of 10.5 tests --echo # End of 10.5 tests
--echo # --echo #
--echo #
--echo # Start of 10.6 tests
--echo #
--echo #
--echo # MDEV-27690 Crash on `CHARACTER SET csname COLLATE DEFAULT` in column definition
--echo #
SELECT * FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) CHARACTER SET latin1 COLLATE DEFAULT PATH '$.name'
)
) AS jt;
CREATE TABLE t1 AS
SELECT * FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) CHARACTER SET latin1 COLLATE DEFAULT PATH '$.name'
)
) AS jt;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # End of 10.6 tests
--echo #

View File

@@ -11476,3 +11476,46 @@ Warning 1292 Truncated incorrect INTEGER value: 'яяя'
# #
# End of 10.5 tests # End of 10.5 tests
# #
#
# Start of 10.9 tests
#
#
# MDEV-28118 Wrong collation of `CAST(.. AS CHAR COLLATE DEFAULT)`
#
SET NAMES utf8mb3 COLLATE utf8mb3_bin;
SELECT COLLATION(CAST('a' AS CHAR COLLATE DEFAULT));
COLLATION(CAST('a' AS CHAR COLLATE DEFAULT))
utf8mb3_general_ci
CREATE TABLE t1 AS SELECT CAST('a' AS CHAR COLLATE DEFAULT) AS c1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(1) CHARACTER SET utf8mb3 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# MDEV-28119 Wrong column collation on MODIFY + CONVERT
#
CREATE TABLE t1 (a CHAR);
ALTER TABLE t1
MODIFY a CHAR COLLATE DEFAULT,
CONVERT TO CHARACTER SET utf8mb3 COLLATE utf8mb3_bin;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(1) CHARACTER SET utf8mb3 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin
DROP TABLE t1;
CREATE TABLE t1 (a CHAR);
ALTER TABLE t1
MODIFY a CHAR BINARY,
CONVERT TO CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3
DROP TABLE t1;
#
# End of 10.9 tests
#

View File

@@ -2357,3 +2357,41 @@ SELECT CAST(_utf8 'яяя' AS INT);
--echo # --echo #
--echo # End of 10.5 tests --echo # End of 10.5 tests
--echo # --echo #
--echo #
--echo # Start of 10.9 tests
--echo #
--echo #
--echo # MDEV-28118 Wrong collation of `CAST(.. AS CHAR COLLATE DEFAULT)`
--echo #
SET NAMES utf8mb3 COLLATE utf8mb3_bin;
SELECT COLLATION(CAST('a' AS CHAR COLLATE DEFAULT));
CREATE TABLE t1 AS SELECT CAST('a' AS CHAR COLLATE DEFAULT) AS c1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # MDEV-28119 Wrong column collation on MODIFY + CONVERT
--echo #
CREATE TABLE t1 (a CHAR);
ALTER TABLE t1
MODIFY a CHAR COLLATE DEFAULT,
CONVERT TO CHARACTER SET utf8mb3 COLLATE utf8mb3_bin;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR);
ALTER TABLE t1
MODIFY a CHAR BINARY,
CONVERT TO CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # End of 10.9 tests
--echo #

View File

@@ -4147,6 +4147,38 @@ EXECUTE IMMEDIATE 'SELECT ''😎'' AS c';
c c
😎 😎
# #
# MDEV-27690 Crash on `CHARACTER SET csname COLLATE DEFAULT` in column definition
#
CREATE TABLE t1 (a CHAR(10) CHARACTER SET utf8mb4 COLLATE DEFAULT);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(10) CHARACTER SET utf8mb4 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SELECT CAST('a' AS CHAR(10) CHARACTER SET utf8mb4 COLLATE DEFAULT);
CAST('a' AS CHAR(10) CHARACTER SET utf8mb4 COLLATE DEFAULT)
a
CREATE TABLE t1 AS
SELECT CAST('a' AS CHAR(10) CHARACTER SET utf8mb4 COLLATE DEFAULT) AS c1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(10) CHARACTER SET utf8mb4 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SELECT COLUMN_GET(COLUMN_CREATE(0, 'string'),0 AS CHAR CHARACTER SET utf8mb4 COLLATE DEFAULT) AS c1;
c1
string
CREATE TABLE t1 AS
SELECT COLUMN_GET(COLUMN_CREATE(0, 'string'),0 AS CHAR CHARACTER SET utf8mb4 COLLATE DEFAULT) AS c1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` longtext CHARACTER SET utf8mb4 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# End of 10.2 tests # End of 10.2 tests
# #
# #
@@ -4167,3 +4199,31 @@ ERROR 42000: COLLATION 'latin1_swedish_ci' is not valid for CHARACTER SET 'utf8m
# #
# End of 10.5 tests # End of 10.5 tests
# #
#
# Start of 10.6 tests
#
#
# MDEV-27690 Crash on `CHARACTER SET csname COLLATE DEFAULT` in column definition
#
SELECT * FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) CHARACTER SET utf8mb4 COLLATE DEFAULT PATH '$.name'
)
) AS jt;
name
Jeans
CREATE TABLE t1 AS
SELECT * FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) CHARACTER SET utf8mb4 COLLATE DEFAULT PATH '$.name'
)
) AS jt;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`name` varchar(10) CHARACTER SET utf8mb4 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# End of 10.6 tests
#

View File

@@ -2040,6 +2040,27 @@ PREPARE stmt FROM 'SELECT ''😎'' AS c';
EXECUTE stmt; EXECUTE stmt;
EXECUTE IMMEDIATE 'SELECT ''😎'' AS c'; EXECUTE IMMEDIATE 'SELECT ''😎'' AS c';
--echo #
--echo # MDEV-27690 Crash on `CHARACTER SET csname COLLATE DEFAULT` in column definition
--echo #
CREATE TABLE t1 (a CHAR(10) CHARACTER SET utf8mb4 COLLATE DEFAULT);
SHOW CREATE TABLE t1;
DROP TABLE t1;
SELECT CAST('a' AS CHAR(10) CHARACTER SET utf8mb4 COLLATE DEFAULT);
CREATE TABLE t1 AS
SELECT CAST('a' AS CHAR(10) CHARACTER SET utf8mb4 COLLATE DEFAULT) AS c1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
SELECT COLUMN_GET(COLUMN_CREATE(0, 'string'),0 AS CHAR CHARACTER SET utf8mb4 COLLATE DEFAULT) AS c1;
CREATE TABLE t1 AS
SELECT COLUMN_GET(COLUMN_CREATE(0, 'string'),0 AS CHAR CHARACTER SET utf8mb4 COLLATE DEFAULT) AS c1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo # --echo #
--echo # End of 10.2 tests --echo # End of 10.2 tests
--echo # --echo #
@@ -2062,3 +2083,30 @@ SELECT 1 COLLATE latin1_swedish_ci;
--echo # --echo #
--echo # End of 10.5 tests --echo # End of 10.5 tests
--echo # --echo #
--echo #
--echo # Start of 10.6 tests
--echo #
--echo #
--echo # MDEV-27690 Crash on `CHARACTER SET csname COLLATE DEFAULT` in column definition
--echo #
SELECT * FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) CHARACTER SET utf8mb4 COLLATE DEFAULT PATH '$.name'
)
) AS jt;
CREATE TABLE t1 AS
SELECT * FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) CHARACTER SET utf8mb4 COLLATE DEFAULT PATH '$.name'
)
) AS jt;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # End of 10.6 tests
--echo #

View File

@@ -987,3 +987,78 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
# #
# End of 10.6 tests # End of 10.6 tests
# #
#
# Start of 10.9 tests
#
#
# MDEV-27743 Remove Lex::charset
#
SELECT collation(name)
FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) PATH '$.name'
)
) AS jt;
collation(name)
utf8mb4_general_ci
SELECT collation(name)
FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) COLLATE DEFAULT PATH '$.name'
)
) AS jt;
collation(name)
utf8mb4_general_ci
SELECT collation(name)
FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) BINARY PATH '$.name'
)
) AS jt;
collation(name)
utf8mb4_bin
CREATE VIEW v1 AS
SELECT *
FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) PATH '$.name'
)
) AS jt;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `jt`.`name` AS `name` from JSON_TABLE('[{"name":"Jeans"}]', '$[*]' COLUMNS (`name` varchar(10) PATH '$.name')) `jt` latin1 latin1_swedish_ci
SELECT collation(name) FROM v1;
collation(name)
utf8mb4_general_ci
DROP VIEW v1;
CREATE VIEW v1 AS
SELECT *
FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) COLLATE DEFAULT PATH '$.name'
)
) AS jt;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `jt`.`name` AS `name` from JSON_TABLE('[{"name":"Jeans"}]', '$[*]' COLUMNS (`name` varchar(10) PATH '$.name')) `jt` latin1 latin1_swedish_ci
SELECT collation(name) FROM v1;
collation(name)
utf8mb4_general_ci
DROP VIEW v1;
CREATE VIEW v1 AS
SELECT *
FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) BINARY PATH '$.name'
)
) AS jt;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `jt`.`name` AS `name` from JSON_TABLE('[{"name":"Jeans"}]', '$[*]' COLUMNS (`name` varchar(10) CHARSET utf8mb4 COLLATE utf8mb4_bin PATH '$.name')) `jt` latin1 latin1_swedish_ci
SELECT collation(name) FROM v1;
collation(name)
utf8mb4_bin
DROP VIEW v1;
#
# End of 10.9 tests
#

View File

@@ -845,3 +845,70 @@ SELECT * FROM json_table('[{"name":"str"}]', '$[*]'
--echo # --echo #
--echo # End of 10.6 tests --echo # End of 10.6 tests
--echo # --echo #
--echo #
--echo # Start of 10.9 tests
--echo #
--echo #
--echo # MDEV-27743 Remove Lex::charset
--echo #
SELECT collation(name)
FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) PATH '$.name'
)
) AS jt;
SELECT collation(name)
FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) COLLATE DEFAULT PATH '$.name'
)
) AS jt;
SELECT collation(name)
FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) BINARY PATH '$.name'
)
) AS jt;
CREATE VIEW v1 AS
SELECT *
FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) PATH '$.name'
)
) AS jt;
SHOW CREATE VIEW v1;
SELECT collation(name) FROM v1;
DROP VIEW v1;
CREATE VIEW v1 AS
SELECT *
FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) COLLATE DEFAULT PATH '$.name'
)
) AS jt;
SHOW CREATE VIEW v1;
SELECT collation(name) FROM v1;
DROP VIEW v1;
CREATE VIEW v1 AS
SELECT *
FROM json_table('[{"name":"Jeans"}]', '$[*]'
COLUMNS(
name VARCHAR(10) BINARY PATH '$.name'
)
) AS jt;
SHOW CREATE VIEW v1;
SELECT collation(name) FROM v1;
DROP VIEW v1;
--echo #
--echo # End of 10.9 tests
--echo #

View File

@@ -18,7 +18,7 @@ grant test_role to test_user@localhost;
set default role test_role for root@localhost; set default role test_role for root@localhost;
drop role test_role; drop role test_role;
drop user test_user@localhost; drop user test_user@localhost;
alter table user add column default_role char(80) binary default '' not null alter table user add column default_role char(80) default '' not null
COLLATE utf8_general_ci COLLATE utf8_general_ci
after is_role; after is_role;
alter table user add max_statement_time decimal(12,6) default 0 not null alter table user add max_statement_time decimal(12,6) default 0 not null

View File

@@ -36,7 +36,7 @@ set default role test_role for root@localhost;
drop role test_role; drop role test_role;
drop user test_user@localhost; drop user test_user@localhost;
alter table user add column default_role char(80) binary default '' not null alter table user add column default_role char(80) default '' not null
COLLATE utf8_general_ci COLLATE utf8_general_ci
after is_role; after is_role;
alter table user add max_statement_time decimal(12,6) default 0 not null alter table user add max_statement_time decimal(12,6) default 0 not null

View File

@@ -162,6 +162,7 @@ SET (SQL_SOURCE
semisync.cc semisync_master.cc semisync_slave.cc semisync.cc semisync_master.cc semisync_slave.cc
semisync_master_ack_receiver.cc semisync_master_ack_receiver.cc
sql_schema.cc sql_schema.cc
lex_charset.cc
sql_type.cc sql_mode.cc sql_type_json.cc sql_type.cc sql_mode.cc sql_type_json.cc
sql_type_string.cc sql_type_string.cc
sql_type_geom.cc sql_type_geom.cc

View File

@@ -10410,17 +10410,15 @@ bool Column_definition::prepare_interval_field(MEM_ROOT *mem_root,
bool Column_definition::set_attributes(THD *thd, bool Column_definition::set_attributes(THD *thd,
const Lex_field_type_st &def, const Lex_field_type_st &def,
CHARSET_INFO *cs,
column_definition_type_t type) column_definition_type_t type)
{ {
DBUG_ASSERT(type_handler() == &type_handler_null); DBUG_ASSERT(type_handler() == &type_handler_null);
DBUG_ASSERT(charset == &my_charset_bin || charset == NULL);
DBUG_ASSERT(length == 0); DBUG_ASSERT(length == 0);
DBUG_ASSERT(decimals == 0); DBUG_ASSERT(decimals == 0);
set_handler(def.type_handler()); set_handler(def.type_handler());
return type_handler()->Column_definition_set_attributes(thd, this, return type_handler()->Column_definition_set_attributes(thd, this,
def, cs, type); def, type);
} }

View File

@@ -5299,7 +5299,6 @@ public:
Column_definition(THD *thd, Field *field, Field *orig_field); Column_definition(THD *thd, Field *field, Field *orig_field);
bool set_attributes(THD *thd, bool set_attributes(THD *thd,
const Lex_field_type_st &attr, const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type); column_definition_type_t type);
void create_length_to_internal_length_null() void create_length_to_internal_length_null()
{ {
@@ -5493,6 +5492,24 @@ public:
{ return compression_method_ptr; } { return compression_method_ptr; }
bool check_vcol_for_key(THD *thd) const; bool check_vcol_for_key(THD *thd) const;
void set_lex_charset_collation(const Lex_charset_collation_st &lc)
{
charset= lc.charset_collation();
if (lc.is_contextually_typed_collation())
flags|= CONTEXT_COLLATION_FLAG;
else
flags&= ~CONTEXT_COLLATION_FLAG;
}
Lex_charset_collation lex_charset_collation() const
{
return Lex_charset_collation(
charset,
!charset ? Lex_charset_collation_st::TYPE_EMPTY :
flags & CONTEXT_COLLATION_FLAG ?
Lex_charset_collation_st::TYPE_COLLATE_CONTEXTUALLY_TYPED :
Lex_charset_collation_st::TYPE_CHARACTER_SET);
}
}; };

View File

@@ -3761,26 +3761,41 @@ struct Lex_cast_type_st: public Lex_length_and_dec_st
{ {
private: private:
const Type_handler *m_type_handler; const Type_handler *m_type_handler;
CHARSET_INFO *m_charset;
public: public:
void set(const Type_handler *handler, Lex_length_and_dec_st length_and_dec) void set(const Type_handler *handler,
Lex_length_and_dec_st length_and_dec,
CHARSET_INFO *cs= NULL)
{ {
m_type_handler= handler; m_type_handler= handler;
m_charset= cs;
Lex_length_and_dec_st::operator=(length_and_dec); Lex_length_and_dec_st::operator=(length_and_dec);
} }
bool set(const Type_handler *handler,
const Lex_length_and_dec_st & length_and_dec,
const Lex_charset_collation_st &cscl,
CHARSET_INFO *defcs)
{
CHARSET_INFO *tmp= cscl.resolved_to_character_set(defcs);
if (!tmp)
return true;
set(handler, length_and_dec, tmp);
return false;
}
void set(const Type_handler *handler) void set(const Type_handler *handler)
{ {
m_type_handler= handler; m_type_handler= handler;
m_charset= NULL;
Lex_length_and_dec_st::reset(); Lex_length_and_dec_st::reset();
} }
const Type_handler *type_handler() const { return m_type_handler; } const Type_handler *type_handler() const { return m_type_handler; }
Item *create_typecast_item(THD *thd, Item *item, CHARSET_INFO *charset() const { return m_charset; }
CHARSET_INFO *cs= NULL) const Item *create_typecast_item(THD *thd, Item *item) const
{ {
return m_type_handler-> return m_type_handler->
create_typecast_item(thd, item, Type_cast_attributes(*this, cs)); create_typecast_item(thd, item, Type_cast_attributes(*this, m_charset));
} }
Item *create_typecast_item_or_error(THD *thd, Item *item, Item *create_typecast_item_or_error(THD *thd, Item *item) const;
CHARSET_INFO *cs= NULL) const;
}; };

View File

@@ -716,7 +716,7 @@ bool Create_json_table::add_json_table_fields(THD *thd, TABLE *table,
uint fieldnr= 0; uint fieldnr= 0;
MEM_ROOT *mem_root_save= thd->mem_root; MEM_ROOT *mem_root_save= thd->mem_root;
List_iterator_fast<Json_table_column> jc_i(jt->m_columns); List_iterator_fast<Json_table_column> jc_i(jt->m_columns);
Column_derived_attributes da(NULL); Column_derived_attributes da(&my_charset_utf8mb4_general_ci);
DBUG_ENTER("add_json_table_fields"); DBUG_ENTER("add_json_table_fields");
thd->mem_root= &table->mem_root; thd->mem_root= &table->mem_root;
@@ -733,8 +733,6 @@ bool Create_json_table::add_json_table_fields(THD *thd, TABLE *table,
executing a prepared statement for the second time. executing a prepared statement for the second time.
*/ */
sql_f->length= sql_f->char_length; sql_f->length= sql_f->char_length;
if (!sql_f->charset)
sql_f->charset= &my_charset_utf8mb4_general_ci;
if (sql_f->prepare_stage1(thd, thd->mem_root, table->file, if (sql_f->prepare_stage1(thd, thd->mem_root, table->file,
table->file->ha_table_flags(), &da)) table->file->ha_table_flags(), &da))
@@ -873,6 +871,19 @@ int Json_table_column::set(THD *thd, enum_type ctype, const LEX_CSTRING &path,
} }
int Json_table_column::set(THD *thd, enum_type ctype, const LEX_CSTRING &path,
const Lex_charset_collation_st &cl)
{
if (cl.is_empty() || cl.is_contextually_typed_collate_default())
return set(thd, ctype, path, nullptr);
CHARSET_INFO *tmp;
if (!(tmp= cl.resolved_to_character_set(&my_charset_utf8mb4_general_ci)))
return 1;
return set(thd, ctype, path, tmp);
}
static int print_path(String *str, const json_path_t *p) static int print_path(String *str, const json_path_t *p)
{ {
return str->append('\'') || return str->append('\'') ||
@@ -915,7 +926,10 @@ int Json_table_column::print(THD *thd, Field **f, String *str)
if (str->append(column_type) || if (str->append(column_type) ||
((*f)->has_charset() && m_explicit_cs && ((*f)->has_charset() && m_explicit_cs &&
(str->append(STRING_WITH_LEN(" CHARSET ")) || (str->append(STRING_WITH_LEN(" CHARSET ")) ||
str->append(&m_explicit_cs->cs_name))) || str->append(&m_explicit_cs->cs_name) ||
(!(m_explicit_cs->state & MY_CS_PRIMARY) &&
(str->append(STRING_WITH_LEN(" COLLATE ")) ||
str->append(&m_explicit_cs->coll_name))))) ||
str->append(m_column_type == PATH ? &path : &exists_path) || str->append(m_column_type == PATH ? &path : &exists_path) ||
print_path(str, &m_path)) print_path(str, &m_path))
return 1; return 1;

View File

@@ -160,6 +160,8 @@ public:
m_column_type= ctype; m_column_type= ctype;
} }
int set(THD *thd, enum_type ctype, const LEX_CSTRING &path, CHARSET_INFO *cs); int set(THD *thd, enum_type ctype, const LEX_CSTRING &path, CHARSET_INFO *cs);
int set(THD *thd, enum_type ctype, const LEX_CSTRING &path,
const Lex_charset_collation_st &cl);
Json_table_column(Create_field *f, Json_table_nested_path *nest) : Json_table_column(Create_field *f, Json_table_nested_path *nest) :
m_field(f), m_nest(nest), m_explicit_cs(NULL) m_field(f), m_nest(nest), m_explicit_cs(NULL)
{ {

339
sql/lex_charset.cc Normal file
View File

@@ -0,0 +1,339 @@
/* Copyright (c) 2021, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
#include "my_global.h"
#include "my_sys.h"
#include "m_ctype.h"
#include "lex_charset.h"
#include "mysqld_error.h"
/** find a collation with binary comparison rules
*/
CHARSET_INFO *Lex_charset_collation_st::find_bin_collation(CHARSET_INFO *cs)
{
/*
We don't need to handle old_mode=UTF8_IS_UTF8MB3 here,
because "cs" points to a real character set name.
It can be either "utf8mb3" or "utf8mb4". It cannot be "utf8".
No thd->get_utf8_flag() flag passed to get_charset_by_csname().
*/
DBUG_ASSERT(cs->cs_name.length !=4 || memcmp(cs->cs_name.str, "utf8", 4));
/*
CREATE TABLE t1 (a CHAR(10) BINARY)
CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
Nothing to do, we have the binary collation already.
*/
if (cs->state & MY_CS_BINSORT)
return cs;
// CREATE TABLE t1 (a CHAR(10) BINARY) CHARACTER SET utf8mb4;
if (!(cs= get_charset_by_csname(cs->cs_name.str, MY_CS_BINSORT, MYF(0))))
{
char tmp[65];
strxnmov(tmp, sizeof(tmp)-1, cs->cs_name.str, "_bin", NULL);
my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
}
return cs;
}
CHARSET_INFO *Lex_charset_collation_st::find_default_collation(CHARSET_INFO *cs)
{
// See comments in find_bin_collation()
DBUG_ASSERT(cs->cs_name.length !=4 || memcmp(cs->cs_name.str, "utf8", 4));
/*
CREATE TABLE t1 (a CHAR(10) COLLATE DEFAULT) CHARACTER SET utf8mb4;
Nothing to do, we have the default collation already.
*/
if (cs->state & MY_CS_PRIMARY)
return cs;
/*
CREATE TABLE t1 (a CHAR(10) COLLATE DEFAULT)
CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
Don't need to handle old_mode=UTF8_IS_UTF8MB3 here.
See comments in find_bin_collation.
*/
cs= get_charset_by_csname(cs->cs_name.str, MY_CS_PRIMARY, MYF(MY_WME));
/*
The above should never fail, as we have default collations for
all character sets.
*/
DBUG_ASSERT(cs);
return cs;
}
bool Lex_charset_collation_st::set_charset_collate_exact(CHARSET_INFO *cs,
CHARSET_INFO *cl)
{
DBUG_ASSERT(cs != nullptr && cl != nullptr);
if (!my_charset_same(cl, cs))
{
my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
cl->coll_name.str, cs->cs_name.str);
return true;
}
set_collate_exact(cl);
return false;
}
/*
Resolve an empty or a contextually typed collation according to the
upper level default character set (and optionally a collation), e.g.:
CREATE TABLE t1 (a CHAR(10)) CHARACTER SET latin1;
CREATE TABLE t1 (a CHAR(10) BINARY) CHARACTER SET latin1;
CREATE TABLE t1 (a CHAR(10) COLLATE DEFAULT)
CHARACTER SET latin1 COLLATE latin1_bin;
"this" is the COLLATE clause (e.g. of a column)
"def" is the upper level CHARACTER SET clause (e.g. of a table)
*/
CHARSET_INFO *
Lex_charset_collation_st::resolved_to_character_set(CHARSET_INFO *def) const
{
DBUG_ASSERT(def);
switch (m_type) {
case TYPE_EMPTY:
return def;
case TYPE_CHARACTER_SET:
DBUG_ASSERT(m_ci);
return m_ci;
case TYPE_COLLATE_EXACT:
DBUG_ASSERT(m_ci);
return m_ci;
case TYPE_COLLATE_CONTEXTUALLY_TYPED:
break;
}
// Contextually typed
DBUG_ASSERT(m_ci);
if (is_contextually_typed_binary_style()) // CHAR(10) BINARY
return find_bin_collation(def);
if (is_contextually_typed_collate_default()) // CHAR(10) COLLATE DEFAULT
return find_default_collation(def);
/*
Non-binary and non-default contextually typed collation.
We don't have such yet - the parser cannot produce this.
But will have soon, e.g. "uca1400_as_ci".
*/
DBUG_ASSERT(0);
return NULL;
}
/*
Merge the CHARACTER SET clause to:
- an empty COLLATE clause
- an explicitly typed collation name
- a contextually typed collation
"this" corresponds to `CHARACTER SET xxx [BINARY]`
"cl" corresponds to the COLLATE clause
*/
bool
Lex_charset_collation_st::
merge_charset_clause_and_collate_clause(const Lex_charset_collation_st &cl)
{
if (cl.is_empty()) // No COLLATE clause
return false;
switch (m_type) {
case TYPE_EMPTY:
/*
No CHARACTER SET clause
CHAR(10) NOT NULL COLLATE latin1_bin
CHAR(10) NOT NULL COLLATE DEFAULT
*/
*this= cl;
return false;
case TYPE_CHARACTER_SET:
case TYPE_COLLATE_EXACT:
{
Lex_explicit_charset_opt_collate ecs(m_ci, m_type == TYPE_COLLATE_EXACT);
if (ecs.merge_collate_or_error(cl))
return true;
set_collate_exact(ecs.charset_and_collation());
return false;
}
case TYPE_COLLATE_CONTEXTUALLY_TYPED:
break;
}
if (is_contextually_typed_collation())
{
if (cl.is_contextually_typed_collation())
{
/*
CONTEXT + CONTEXT:
CHAR(10) BINARY .. COLLATE DEFAULT - not supported by the parser
CHAR(10) BINARY .. COLLATE uca1400_as_ci - not supported yet
*/
DBUG_ASSERT(0); // Not possible yet
return false;
}
/*
CONTEXT + EXPLICIT
CHAR(10) COLLATE DEFAULT .. COLLATE latin1_swedish_ci
CHAR(10) BINARY .. COLLATE latin1_bin
CHAR(10) COLLATE uca1400_as_ci .. COLLATE latin1_bin
*/
if (is_contextually_typed_collate_default() &&
!(cl.charset_collation()->state & MY_CS_PRIMARY))
{
my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
"COLLATE ", "DEFAULT", "COLLATE ",
cl.charset_collation()->coll_name.str);
return true;
}
if (is_contextually_typed_binary_style() &&
!(cl.charset_collation()->state & MY_CS_BINSORT))
{
my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
"", "BINARY", "COLLATE ", cl.charset_collation()->coll_name.str);
return true;
}
*this= cl;
return false;
}
DBUG_ASSERT(0);
return false;
}
bool
Lex_explicit_charset_opt_collate::
merge_collate_or_error(const Lex_charset_collation_st &cl)
{
DBUG_ASSERT(cl.type() != Lex_charset_collation_st::TYPE_CHARACTER_SET);
switch (cl.type()) {
case Lex_charset_collation_st::TYPE_EMPTY:
return false;
case Lex_charset_collation_st::TYPE_CHARACTER_SET:
DBUG_ASSERT(0);
return false;
case Lex_charset_collation_st::TYPE_COLLATE_EXACT:
/*
EXPLICIT + EXPLICIT
CHAR(10) CHARACTER SET latin1 .. COLLATE latin1_bin
CHAR(10) CHARACTER SET latin1 COLLATE latin1_bin .. COLLATE latin1_bin
CHAR(10) COLLATE latin1_bin .. COLLATE latin1_bin
CHAR(10) COLLATE latin1_bin .. COLLATE latin1_bin
CHAR(10) CHARACTER SET latin1 BINARY .. COLLATE latin1_bin
*/
if (m_with_collate && m_ci != cl.charset_collation())
{
my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
"COLLATE ", m_ci->coll_name.str,
"COLLATE ", cl.charset_collation()->coll_name.str);
return true;
}
if (!my_charset_same(m_ci, cl.charset_collation()))
{
my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
cl.charset_collation()->coll_name.str, m_ci->cs_name.str);
return true;
}
m_ci= cl.charset_collation();
m_with_collate= true;
return false;
case Lex_charset_collation_st::TYPE_COLLATE_CONTEXTUALLY_TYPED:
if (cl.is_contextually_typed_collate_default())
{
/*
SET NAMES latin1 COLLATE DEFAULT;
ALTER TABLE t1 CONVERT TO CHARACTER SET latin1 COLLATE DEFAULT;
*/
CHARSET_INFO *tmp= Lex_charset_collation_st::find_default_collation(m_ci);
if (!tmp)
return true;
m_ci= tmp;
m_with_collate= true;
return false;
}
else
{
/*
EXPLICIT + CONTEXT
CHAR(10) COLLATE latin1_bin .. COLLATE DEFAULT not possible yet
CHAR(10) COLLATE latin1_bin .. COLLATE uca1400_as_ci
*/
DBUG_ASSERT(0); // Not possible yet
return false;
}
}
DBUG_ASSERT(0);
return false;
}
/*
This method is used in the "attribute_list" rule to merge two independent
COLLATE clauses (not belonging to a CHARACTER SET clause).
*/
bool
Lex_charset_collation_st::
merge_collate_clause_and_collate_clause(const Lex_charset_collation_st &cl)
{
/*
"BINARY" and "COLLATE DEFAULT" are not possible
in an independent COLLATE clause in a column attribute.
*/
DBUG_ASSERT(!is_contextually_typed_collation());
DBUG_ASSERT(!cl.is_contextually_typed_collation());
if (cl.is_empty())
return false;
switch (m_type) {
case TYPE_EMPTY:
*this= cl;
return false;
case TYPE_CHARACTER_SET:
DBUG_ASSERT(0);
return false;
case TYPE_COLLATE_EXACT:
case TYPE_COLLATE_CONTEXTUALLY_TYPED:
break;
}
/*
Two independent explicit collations:
CHAR(10) NOT NULL COLLATE latin1_bin DEFAULT 'a' COLLATE latin1_bin
Note, we should perhaps eventually disallow double COLLATE clauses.
But for now let's just disallow only conflicting ones.
*/
if (charset_collation() != cl.charset_collation())
{
my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
"COLLATE ", charset_collation()->coll_name.str,
"COLLATE ", cl.charset_collation()->coll_name.str);
return true;
}
return false;
}

199
sql/lex_charset.h Normal file
View File

@@ -0,0 +1,199 @@
/* Copyright (c) 2021, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
#ifndef LEX_CHARSET_INCLUDED
#define LEX_CHARSET_INCLUDED
/*
Parse time character set and collation.
Can be:
1. Empty (not specified on the column level):
CREATE TABLE t1 (a CHAR(10)) CHARACTER SET latin2; -- (1a)
CREATE TABLE t1 (a CHAR(10)); -- (1b)
2. Precisely typed:
CREATE TABLE t1 (a CHAR(10) COLLATE latin1_bin); -- (2a)
CREATE TABLE t1 (
a CHAR(10) CHARACTER SET latin1 COLLATE latin1_bin); -- (2b)
3. Contextually typed:
CREATE TABLE t2 (a CHAR(10) BINARY) CHARACTER SET latin2; -- (3a)
CREATE TABLE t2 (a CHAR(10) BINARY); -- (3b)
CREATE TABLE t2 (a CHAR(10) COLLATE DEFAULT)
CHARACER SET latin2 COLLATE latin2_bin; -- (3c)
In case of an empty or a contextually typed collation,
it is a subject to later resolution, when the context
character set becomes known in the end of the CREATE statement:
- either after the explicit table level CHARACTER SET, like in (1a,3a,3c)
- or by the inhereted database level CHARACTER SET, like in (1b,3b)
Resolution happens in Type_handler::Column_definition_prepare_stage1().
*/
struct Lex_charset_collation_st
{
public:
enum Type
{
TYPE_EMPTY= 0,
TYPE_CHARACTER_SET= 1,
TYPE_COLLATE_EXACT= 2,
TYPE_COLLATE_CONTEXTUALLY_TYPED= 3
};
// Number of bits required to store enum Type values
#define LEX_CHARSET_COLLATION_TYPE_BITS 2
static_assert(((1<<LEX_CHARSET_COLLATION_TYPE_BITS)-1) >=
TYPE_COLLATE_CONTEXTUALLY_TYPED,
"Lex_charset_collation_st::Type bits check");
protected:
CHARSET_INFO *m_ci;
Type m_type;
public:
static CHARSET_INFO *find_bin_collation(CHARSET_INFO *cs);
static CHARSET_INFO *find_default_collation(CHARSET_INFO *cs);
public:
void init()
{
m_ci= NULL;
m_type= TYPE_EMPTY;
}
bool is_empty() const
{
return m_type == TYPE_EMPTY;
}
void set_charset(CHARSET_INFO *cs)
{
DBUG_ASSERT(cs);
m_ci= cs;
m_type= TYPE_CHARACTER_SET;
}
void set_charset_collate_default(CHARSET_INFO *cs)
{
DBUG_ASSERT(cs);
m_ci= cs;
m_type= TYPE_COLLATE_EXACT;
}
bool set_charset_collate_binary(CHARSET_INFO *cs)
{
DBUG_ASSERT(cs);
if (!(cs= find_bin_collation(cs)))
return true;
m_ci= cs;
m_type= TYPE_COLLATE_EXACT;
return false;
}
bool set_charset_collate_exact(CHARSET_INFO *cs,
CHARSET_INFO *cl);
void set_collate_default()
{
m_ci= &my_collation_contextually_typed_default;
m_type= TYPE_COLLATE_CONTEXTUALLY_TYPED;
}
void set_contextually_typed_binary_style()
{
m_ci= &my_collation_contextually_typed_binary;
m_type= TYPE_COLLATE_CONTEXTUALLY_TYPED;
}
bool is_contextually_typed_collate_default() const
{
return m_ci == &my_collation_contextually_typed_default;
}
bool is_contextually_typed_binary_style() const
{
return m_ci == &my_collation_contextually_typed_binary;
}
void set_collate_exact(CHARSET_INFO *cl)
{
DBUG_ASSERT(cl);
m_ci= cl;
m_type= TYPE_COLLATE_EXACT;
}
CHARSET_INFO *charset_collation() const
{
return m_ci;
}
Type type() const
{
return m_type;
}
bool is_contextually_typed_collation() const
{
return m_type == TYPE_COLLATE_CONTEXTUALLY_TYPED;
}
CHARSET_INFO *resolved_to_character_set(CHARSET_INFO *cs) const;
bool merge_charset_clause_and_collate_clause(const Lex_charset_collation_st &cl);
bool merge_collate_clause_and_collate_clause(const Lex_charset_collation_st &cl);
};
/*
CHARACTER SET cs [COLLATE cl]
*/
class Lex_explicit_charset_opt_collate
{
CHARSET_INFO *m_ci;
bool m_with_collate;
public:
Lex_explicit_charset_opt_collate(CHARSET_INFO *ci, bool with_collate)
:m_ci(ci), m_with_collate(with_collate)
{
DBUG_ASSERT(m_ci);
// Item_func_set_collation uses non-default collations in "ci"
//DBUG_ASSERT(m_ci->default_flag() || m_with_collate);
}
/*
Merge to another COLLATE clause. So the full syntax looks like:
CHARACTER SET cs [COLLATE cl] ... COLLATE cl2
*/
bool merge_collate_or_error(const Lex_charset_collation_st &cl);
bool merge_opt_collate_or_error(const Lex_charset_collation_st &cl)
{
if (cl.is_empty())
return false;
return merge_collate_or_error(cl);
}
CHARSET_INFO *charset_and_collation() const { return m_ci; }
bool with_collate() const { return m_with_collate; }
};
class Lex_charset_collation: public Lex_charset_collation_st
{
public:
Lex_charset_collation()
{
init();
}
Lex_charset_collation(CHARSET_INFO *collation, Type type)
{
DBUG_ASSERT(collation || type == TYPE_EMPTY);
m_ci= collation;
m_type= type;
}
static Lex_charset_collation national(bool bin_mod)
{
return bin_mod ?
Lex_charset_collation(&my_charset_utf8mb3_bin, TYPE_COLLATE_EXACT) :
Lex_charset_collation(&my_charset_utf8mb3_general_ci, TYPE_CHARACTER_SET);
}
};
#endif // LEX_CHARSET_INCLUDED

View File

@@ -543,36 +543,10 @@ bool LEX::add_alter_list(LEX_CSTRING name, LEX_CSTRING new_name, bool exists)
void LEX::init_last_field(Column_definition *field, void LEX::init_last_field(Column_definition *field,
const LEX_CSTRING *field_name, const LEX_CSTRING *field_name)
const CHARSET_INFO *cs)
{ {
last_field= field; last_field= field;
field->field_name= *field_name; field->field_name= *field_name;
/* reset LEX fields that are used in Create_field::set_and_check() */
charset= cs;
}
bool LEX::set_bincmp(CHARSET_INFO *cs, bool bin)
{
/*
if charset is NULL - we're parsing a field declaration.
we cannot call find_bin_collation for a field here, because actual
field charset is determined in get_sql_field_charset() much later.
so we only set a flag.
*/
if (!charset)
{
charset= cs;
last_field->flags|= bin ? BINCMP_FLAG : 0;
return false;
}
charset= bin ? find_bin_collation(cs ? cs : charset)
: cs ? cs : charset;
return charset == NULL;
} }
@@ -6392,8 +6366,7 @@ sp_variable *LEX::sp_param_init(LEX_CSTRING *name)
return NULL; return NULL;
} }
sp_variable *spvar= spcont->add_variable(thd, name); sp_variable *spvar= spcont->add_variable(thd, name);
init_last_field(&spvar->field_def, name, init_last_field(&spvar->field_def, name);
thd->variables.collation_database);
return spvar; return spvar;
} }
@@ -6402,8 +6375,7 @@ bool LEX::sp_param_fill_definition(sp_variable *spvar,
const Lex_field_type_st &def) const Lex_field_type_st &def)
{ {
return return
last_field->set_attributes(thd, def, charset, last_field->set_attributes(thd, def, COLUMN_DEFINITION_ROUTINE_PARAM) ||
COLUMN_DEFINITION_ROUTINE_PARAM) ||
sphead->fill_spvar_definition(thd, last_field, &spvar->name); sphead->fill_spvar_definition(thd, last_field, &spvar->name);
} }
@@ -6411,8 +6383,7 @@ bool LEX::sp_param_fill_definition(sp_variable *spvar,
bool LEX::sf_return_fill_definition(const Lex_field_type_st &def) bool LEX::sf_return_fill_definition(const Lex_field_type_st &def)
{ {
return return
last_field->set_attributes(thd, def, charset, last_field->set_attributes(thd, def, COLUMN_DEFINITION_FUNCTION_RETURN) ||
COLUMN_DEFINITION_FUNCTION_RETURN) ||
sphead->fill_field_definition(thd, last_field); sphead->fill_field_definition(thd, last_field);
} }
@@ -6492,8 +6463,7 @@ void LEX::sp_variable_declarations_init(THD *thd, int nvars)
sphead->reset_lex(thd); sphead->reset_lex(thd);
spcont->declare_var_boundary(nvars); spcont->declare_var_boundary(nvars);
thd->lex->init_last_field(&spvar->field_def, &spvar->name, thd->lex->init_last_field(&spvar->field_def, &spvar->name);
thd->variables.collation_database);
} }
@@ -11465,16 +11435,15 @@ Spvar_definition *LEX::row_field_name(THD *thd, const Lex_ident_sys_st &name)
} }
if (unlikely(!(res= new (thd->mem_root) Spvar_definition()))) if (unlikely(!(res= new (thd->mem_root) Spvar_definition())))
return NULL; return NULL;
init_last_field(res, &name, thd->variables.collation_database); init_last_field(res, &name);
return res; return res;
} }
Item * Item *
Lex_cast_type_st::create_typecast_item_or_error(THD *thd, Item *item, Lex_cast_type_st::create_typecast_item_or_error(THD *thd, Item *item) const
CHARSET_INFO *cs) const
{ {
Item *tmp= create_typecast_item(thd, item, cs); Item *tmp= create_typecast_item(thd, item);
if (!tmp) if (!tmp)
{ {
Name name= m_type_handler->name(); Name name= m_type_handler->name();
@@ -11534,8 +11503,7 @@ bool LEX::set_field_type_udt(Lex_field_type_st *type,
const Type_handler *h; const Type_handler *h;
if (!(h= Type_handler::handler_by_name_or_error(thd, name))) if (!(h= Type_handler::handler_by_name_or_error(thd, name)))
return true; return true;
type->set(h, attr); type->set(h, attr, &my_charset_bin);
charset= &my_charset_bin;
return false; return false;
} }
@@ -11547,7 +11515,6 @@ bool LEX::set_cast_type_udt(Lex_cast_type_st *type,
if (!(h= Type_handler::handler_by_name_or_error(thd, name))) if (!(h= Type_handler::handler_by_name_or_error(thd, name)))
return true; return true;
type->set(h); type->set(h);
charset= NULL;
return false; return false;
} }

View File

@@ -3192,8 +3192,6 @@ public:
/* Query Plan Footprint of a currently running select */ /* Query Plan Footprint of a currently running select */
Explain_query *explain; Explain_query *explain;
// type information
CHARSET_INFO *charset;
/* /*
LEX which represents current statement (conventional, SP or PS) LEX which represents current statement (conventional, SP or PS)
@@ -3800,14 +3798,12 @@ public:
bool is_analyze, bool *printed_anything); bool is_analyze, bool *printed_anything);
bool restore_set_statement_var(); bool restore_set_statement_var();
void init_last_field(Column_definition *field, const LEX_CSTRING *name, void init_last_field(Column_definition *field, const LEX_CSTRING *name);
const CHARSET_INFO *cs);
bool last_field_generated_always_as_row_start_or_end(Lex_ident *p, bool last_field_generated_always_as_row_start_or_end(Lex_ident *p,
const char *type, const char *type,
uint flags); uint flags);
bool last_field_generated_always_as_row_start(); bool last_field_generated_always_as_row_start();
bool last_field_generated_always_as_row_end(); bool last_field_generated_always_as_row_end();
bool set_bincmp(CHARSET_INFO *cs, bool bin);
bool new_sp_instr_stmt(THD *, const LEX_CSTRING &prefix, bool new_sp_instr_stmt(THD *, const LEX_CSTRING &prefix,
const LEX_CSTRING &suffix); const LEX_CSTRING &suffix);

View File

@@ -10463,24 +10463,6 @@ merge_charset_and_collation(CHARSET_INFO *cs, CHARSET_INFO *cl)
return cs; return cs;
} }
/** find a collation with binary comparison rules
*/
CHARSET_INFO *find_bin_collation(CHARSET_INFO *cs)
{
const char *csname= cs->cs_name.str;
THD *thd= current_thd;
myf utf8_flag= thd->get_utf8_flag();
cs= get_charset_by_csname(csname, MY_CS_BINSORT, MYF(utf8_flag));
if (!cs)
{
char tmp[65];
strxnmov(tmp, sizeof(tmp)-1, csname, "_bin", NULL);
my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
}
return cs;
}
void LEX::mark_first_table_as_inserting() void LEX::mark_first_table_as_inserting()
{ {
TABLE_LIST *t= first_select_lex()->table_list.first; TABLE_LIST *t= first_select_lex()->table_list.first;

View File

@@ -79,7 +79,6 @@ bool check_string_char_length(const LEX_CSTRING *str, uint err_msg,
bool no_error); bool no_error);
bool check_ident_length(const LEX_CSTRING *ident); bool check_ident_length(const LEX_CSTRING *ident);
CHARSET_INFO* merge_charset_and_collation(CHARSET_INFO *cs, CHARSET_INFO *cl); CHARSET_INFO* merge_charset_and_collation(CHARSET_INFO *cs, CHARSET_INFO *cl);
CHARSET_INFO *find_bin_collation(CHARSET_INFO *cs);
bool check_host_name(LEX_CSTRING *str); bool check_host_name(LEX_CSTRING *str);
bool check_identifier_name(LEX_CSTRING *str, uint max_char_length, bool check_identifier_name(LEX_CSTRING *str, uint max_char_length,
uint err_code, const char *param_for_err_msg); uint err_code, const char *param_for_err_msg);

View File

@@ -2190,12 +2190,27 @@ bool check_duplicates_in_interval(const char *set_or_name,
} }
/*
Resolves the column collation if:
- it was not typed at all, or
- it was contextually typed
according to the table level character set.
Generates an error to the diagnostics area in case of a failure.
*/
bool Column_definition:: bool Column_definition::
prepare_charset_for_string(const Column_derived_attributes *dattr) prepare_charset_for_string(const Column_derived_attributes *dattr)
{ {
if (!charset) CHARSET_INFO *tmp= lex_charset_collation().
charset= dattr->charset(); resolved_to_character_set(dattr->charset());
return (flags & BINCMP_FLAG) && !(charset= find_bin_collation(charset)); if (!tmp)
return true;
charset= tmp;
/*
Remove the "is contextually typed collation" indicator on success,
for safety.
*/
flags&= ~CONTEXT_COLLATION_FLAG;
return false;
} }
@@ -3959,8 +3974,7 @@ bool Column_definition::prepare_blob_field(THD *thd)
bool Column_definition::sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root) bool Column_definition::sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root)
{ {
DBUG_ASSERT(charset); const Column_derived_attributes dattr(thd->variables.collation_database);
const Column_derived_attributes dattr(&my_charset_bin);
return prepare_stage1(thd, mem_root, NULL, HA_CAN_GEOMETRY, &dattr) || return prepare_stage1(thd, mem_root, NULL, HA_CAN_GEOMETRY, &dattr) ||
prepare_stage2(NULL, HA_CAN_GEOMETRY); prepare_stage2(NULL, HA_CAN_GEOMETRY);
} }

View File

@@ -2713,11 +2713,10 @@ bool
Type_handler::Column_definition_set_attributes(THD *thd, Type_handler::Column_definition_set_attributes(THD *thd,
Column_definition *def, Column_definition *def,
const Lex_field_type_st &attr, const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type) column_definition_type_t type)
const const
{ {
def->charset= cs; def->set_lex_charset_collation(attr.lex_charset_collation());
def->set_length_and_dec(attr); def->set_length_and_dec(attr);
return false; return false;
} }
@@ -2746,11 +2745,10 @@ Type_handler_string::Column_definition_set_attributes(
THD *thd, THD *thd,
Column_definition *def, Column_definition *def,
const Lex_field_type_st &attr, const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type) column_definition_type_t type)
const const
{ {
Type_handler::Column_definition_set_attributes(thd, def, attr, cs, type); Type_handler::Column_definition_set_attributes(thd, def, attr, type);
if (attr.has_explicit_length()) if (attr.has_explicit_length())
return false; return false;
switch (type) { switch (type) {
@@ -2778,11 +2776,10 @@ Type_handler_varchar::Column_definition_set_attributes(
THD *thd, THD *thd,
Column_definition *def, Column_definition *def,
const Lex_field_type_st &attr, const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type) column_definition_type_t type)
const const
{ {
Type_handler::Column_definition_set_attributes(thd, def, attr, cs, type); Type_handler::Column_definition_set_attributes(thd, def, attr, type);
if (attr.has_explicit_length()) if (attr.has_explicit_length())
return false; return false;
switch (type) { switch (type) {
@@ -3156,7 +3153,7 @@ bool Type_handler_general_purpose_string::
Change character sets for all varchar/char/text columns, Change character sets for all varchar/char/text columns,
but do not touch varbinary/binary/blob columns. but do not touch varbinary/binary/blob columns.
*/ */
if (defcs != &my_charset_bin) if (!(def->flags & CONTEXT_COLLATION_FLAG) && defcs != &my_charset_bin)
def->charset= bulk_alter_attr->alter_table_convert_to_charset(); def->charset= bulk_alter_attr->alter_table_convert_to_charset();
return false; return false;
}; };
@@ -4267,10 +4264,9 @@ Type_handler_timestamp_common::
Column_definition_set_attributes(THD *thd, Column_definition_set_attributes(THD *thd,
Column_definition *def, Column_definition *def,
const Lex_field_type_st &attr, const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type) const column_definition_type_t type) const
{ {
Type_handler::Column_definition_set_attributes(thd, def, attr, cs, type); Type_handler::Column_definition_set_attributes(thd, def, attr, type);
if (!opt_explicit_defaults_for_timestamp) if (!opt_explicit_defaults_for_timestamp)
def->flags|= NOT_NULL_FLAG; def->flags|= NOT_NULL_FLAG;
return false; return false;

View File

@@ -3924,7 +3924,6 @@ public:
virtual bool Column_definition_set_attributes(THD *thd, virtual bool Column_definition_set_attributes(THD *thd,
Column_definition *def, Column_definition *def,
const Lex_field_type_st &attr, const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type) column_definition_type_t type)
const; const;
// Fix attributes after the parser // Fix attributes after the parser
@@ -6659,7 +6658,6 @@ public:
bool Column_definition_set_attributes(THD *thd, bool Column_definition_set_attributes(THD *thd,
Column_definition *def, Column_definition *def,
const Lex_field_type_st &attr, const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type) column_definition_type_t type)
const override; const override;
}; };
@@ -6912,7 +6910,6 @@ public:
bool Column_definition_set_attributes(THD *thd, bool Column_definition_set_attributes(THD *thd,
Column_definition *def, Column_definition *def,
const Lex_field_type_st &attr, const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type) column_definition_type_t type)
const override; const override;
bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_fix_attributes(Column_definition *c) const override;
@@ -7009,7 +7006,6 @@ public:
bool Column_definition_set_attributes(THD *thd, bool Column_definition_set_attributes(THD *thd,
Column_definition *def, Column_definition *def,
const Lex_field_type_st &attr, const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type) column_definition_type_t type)
const override; const override;
bool Column_definition_fix_attributes(Column_definition *c) const override; bool Column_definition_fix_attributes(Column_definition *c) const override;

View File

@@ -193,14 +193,6 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)()
#endif #endif
#define bincmp_collation(X,Y) \
do \
{ \
if (unlikely(Lex->set_bincmp(X,Y))) \
MYSQL_YYABORT; \
} while(0)
%} %}
%union { %union {
int num; int num;
@@ -221,6 +213,7 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)()
Lex_length_and_dec_st Lex_length_and_dec; Lex_length_and_dec_st Lex_length_and_dec;
Lex_cast_type_st Lex_cast_type; Lex_cast_type_st Lex_cast_type;
Lex_field_type_st Lex_field_type; Lex_field_type_st Lex_field_type;
Lex_charset_collation_st Lex_charset_collation;
Lex_dyncol_type_st Lex_dyncol_type; Lex_dyncol_type_st Lex_dyncol_type;
Lex_for_loop_st for_loop; Lex_for_loop_st for_loop;
Lex_for_loop_bounds_st for_loop_bounds; Lex_for_loop_bounds_st for_loop_bounds;
@@ -1386,6 +1379,15 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
field_type_misc field_type_misc
json_table_field_type json_table_field_type
%type <Lex_charset_collation>
binary
opt_binary
opt_binary_and_compression
attribute
attribute_list
field_def
%type <Lex_dyncol_type> opt_dyncol_type dyncol_type %type <Lex_dyncol_type> opt_dyncol_type dyncol_type
numeric_dyncol_type temporal_dyncol_type string_dyncol_type numeric_dyncol_type temporal_dyncol_type string_dyncol_type
@@ -1575,8 +1577,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
text_or_password text_or_password
%type <charset> %type <charset>
opt_collate opt_collate_or_default
collate
charset_name charset_name
charset_or_alias charset_or_alias
charset_name_or_default charset_name_or_default
@@ -1658,14 +1659,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
delete_limit_clause fields opt_values values delete_limit_clause fields opt_values values
no_braces_with_names opt_values_with_names values_with_names no_braces_with_names opt_values_with_names values_with_names
procedure_list procedure_list2 procedure_item procedure_list procedure_list2 procedure_item
field_def handler opt_generated_always handler opt_generated_always
opt_ignore opt_column opt_restrict opt_ignore opt_column opt_restrict
grant revoke set lock unlock string_list grant revoke set lock unlock string_list
opt_binary table_lock_list table_lock table_lock_list table_lock
ref_list opt_match_clause opt_on_update_delete use ref_list opt_match_clause opt_on_update_delete use
opt_delete_options opt_delete_option varchar nchar nvarchar opt_delete_options opt_delete_option varchar nchar nvarchar
opt_outer table_list table_name table_alias_ref_list table_alias_ref opt_outer table_list table_name table_alias_ref_list table_alias_ref
attribute attribute_list
compressed_deprecated_data_type_attribute compressed_deprecated_data_type_attribute
compressed_deprecated_column_attribute compressed_deprecated_column_attribute
grant_list grant_list
@@ -3124,7 +3124,7 @@ optionally_qualified_column_ident:
row_field_definition: row_field_definition:
row_field_name field_type row_field_name field_type
{ {
Lex->last_field->set_attributes(thd, $2, Lex->charset, Lex->last_field->set_attributes(thd, $2,
COLUMN_DEFINITION_ROUTINE_LOCAL); COLUMN_DEFINITION_ROUTINE_LOCAL);
} }
; ;
@@ -3157,7 +3157,7 @@ sp_decl_variable_list:
sp_decl_idents_init_vars sp_decl_idents_init_vars
field_type field_type
{ {
Lex->last_field->set_attributes(thd, $2, Lex->charset, Lex->last_field->set_attributes(thd, $2,
COLUMN_DEFINITION_ROUTINE_LOCAL); COLUMN_DEFINITION_ROUTINE_LOCAL);
} }
sp_opt_default sp_opt_default
@@ -5723,7 +5723,7 @@ field_spec:
if (unlikely(!f)) if (unlikely(!f))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->init_last_field(f, &$1, NULL); lex->init_last_field(f, &$1);
$<create_field>$= f; $<create_field>$= f;
lex->parsing_options.lookup_keywords_after_qualifier= true; lex->parsing_options.lookup_keywords_after_qualifier= true;
} }
@@ -5751,10 +5751,16 @@ field_spec:
field_type_or_serial: field_type_or_serial:
qualified_field_type qualified_field_type
{ {
Lex->last_field->set_attributes(thd, $1, Lex->charset, Lex->last_field->set_attributes(thd, $1,
COLUMN_DEFINITION_TABLE_FIELD); COLUMN_DEFINITION_TABLE_FIELD);
} }
field_def field_def
{
Lex_charset_collation tmp= $1.lex_charset_collation();
if (tmp.merge_charset_clause_and_collate_clause($3))
MYSQL_YYABORT;
Lex->last_field->set_lex_charset_collation(tmp);
}
| SERIAL_SYM | SERIAL_SYM
{ {
Lex->last_field->set_handler(&type_handler_ulonglong); Lex->last_field->set_handler(&type_handler_ulonglong);
@@ -5786,25 +5792,34 @@ opt_asrow_attribute_list:
; ;
field_def: field_def:
/* empty */ { } /* empty */ { $$.init(); }
| attribute_list | attribute_list
| attribute_list compressed_deprecated_column_attribute | attribute_list compressed_deprecated_column_attribute { $$= $1; }
| attribute_list compressed_deprecated_column_attribute attribute_list | attribute_list compressed_deprecated_column_attribute attribute_list
{
if (($$= $1).merge_collate_clause_and_collate_clause($3))
MYSQL_YYABORT;
}
| opt_generated_always AS virtual_column_func | opt_generated_always AS virtual_column_func
{ {
Lex->last_field->vcol_info= $3; Lex->last_field->vcol_info= $3;
Lex->last_field->flags&= ~NOT_NULL_FLAG; // undo automatic NOT NULL for timestamps Lex->last_field->flags&= ~NOT_NULL_FLAG; // undo automatic NOT NULL for timestamps
} }
vcol_opt_specifier vcol_opt_attribute vcol_opt_specifier vcol_opt_attribute
{
$$.init();
}
| opt_generated_always AS ROW_SYM START_SYM opt_asrow_attribute | opt_generated_always AS ROW_SYM START_SYM opt_asrow_attribute
{ {
if (Lex->last_field_generated_always_as_row_start()) if (Lex->last_field_generated_always_as_row_start())
MYSQL_YYABORT; MYSQL_YYABORT;
$$.init();
} }
| opt_generated_always AS ROW_SYM END opt_asrow_attribute | opt_generated_always AS ROW_SYM END opt_asrow_attribute
{ {
if (Lex->last_field_generated_always_as_row_end()) if (Lex->last_field_generated_always_as_row_end())
MYSQL_YYABORT; MYSQL_YYABORT;
$$.init();
} }
; ;
@@ -6017,49 +6032,46 @@ field_type_numeric:
opt_binary_and_compression: opt_binary_and_compression:
/* empty */ /* empty */ { $$.init(); }
| binary | binary { $$= $1; }
| binary compressed_deprecated_data_type_attribute | binary compressed_deprecated_data_type_attribute { $$= $1; }
| compressed opt_binary | compressed opt_binary { $$= $2; }
; ;
field_type_string: field_type_string:
char opt_field_length opt_binary char opt_field_length opt_binary
{ {
$$.set(&type_handler_string, $2); $$.set(&type_handler_string, $2, $3);
} }
| nchar opt_field_length opt_bin_mod | nchar opt_field_length opt_bin_mod
{ {
$$.set(&type_handler_string, $2); $$.set(&type_handler_string, $2,
bincmp_collation(national_charset_info, $3); Lex_charset_collation::national($3));
} }
| BINARY opt_field_length | BINARY opt_field_length
{ {
Lex->charset=&my_charset_bin; $$.set(&type_handler_string, $2, &my_charset_bin);
$$.set(&type_handler_string, $2);
} }
| varchar opt_field_length opt_binary_and_compression | varchar opt_field_length opt_binary_and_compression
{ {
$$.set(&type_handler_varchar, $2); $$.set(&type_handler_varchar, $2, $3);
} }
| VARCHAR2_ORACLE_SYM opt_field_length opt_binary_and_compression | VARCHAR2_ORACLE_SYM opt_field_length opt_binary_and_compression
{ {
$$.set(&type_handler_varchar, $2); $$.set(&type_handler_varchar, $2, $3);
} }
| nvarchar opt_field_length opt_compressed opt_bin_mod | nvarchar opt_field_length opt_compressed opt_bin_mod
{ {
$$.set(&type_handler_varchar, $2); $$.set(&type_handler_varchar, $2,
bincmp_collation(national_charset_info, $4); Lex_charset_collation::national($4));
} }
| VARBINARY opt_field_length opt_compressed | VARBINARY opt_field_length opt_compressed
{ {
Lex->charset=&my_charset_bin; $$.set(&type_handler_varchar, $2, &my_charset_bin);
$$.set(&type_handler_varchar, $2);
} }
| RAW_ORACLE_SYM opt_field_length opt_compressed | RAW_ORACLE_SYM opt_field_length opt_compressed
{ {
Lex->charset= &my_charset_bin; $$.set(&type_handler_varchar, $2, &my_charset_bin);
$$.set(&type_handler_varchar, $2);
} }
; ;
@@ -6105,65 +6117,57 @@ field_type_temporal:
field_type_lob: field_type_lob:
TINYBLOB opt_compressed TINYBLOB opt_compressed
{ {
Lex->charset=&my_charset_bin; $$.set(&type_handler_tiny_blob, &my_charset_bin);
$$.set(&type_handler_tiny_blob);
} }
| BLOB_MARIADB_SYM opt_field_length opt_compressed | BLOB_MARIADB_SYM opt_field_length opt_compressed
{ {
Lex->charset=&my_charset_bin; $$.set(&type_handler_blob, $2, &my_charset_bin);
$$.set(&type_handler_blob, $2);
} }
| BLOB_ORACLE_SYM field_length opt_compressed | BLOB_ORACLE_SYM field_length opt_compressed
{ {
Lex->charset=&my_charset_bin; $$.set(&type_handler_blob, $2, &my_charset_bin);
$$.set(&type_handler_blob, $2);
} }
| BLOB_ORACLE_SYM opt_compressed | BLOB_ORACLE_SYM opt_compressed
{ {
Lex->charset=&my_charset_bin; $$.set(&type_handler_long_blob, &my_charset_bin);
$$.set(&type_handler_long_blob);
} }
| MEDIUMBLOB opt_compressed | MEDIUMBLOB opt_compressed
{ {
Lex->charset=&my_charset_bin; $$.set(&type_handler_medium_blob, &my_charset_bin);
$$.set(&type_handler_medium_blob);
} }
| LONGBLOB opt_compressed | LONGBLOB opt_compressed
{ {
Lex->charset=&my_charset_bin; $$.set(&type_handler_long_blob, &my_charset_bin);
$$.set(&type_handler_long_blob);
} }
| LONG_SYM VARBINARY opt_compressed | LONG_SYM VARBINARY opt_compressed
{ {
Lex->charset=&my_charset_bin; $$.set(&type_handler_medium_blob, &my_charset_bin);
$$.set(&type_handler_medium_blob);
} }
| LONG_SYM varchar opt_binary_and_compression | LONG_SYM varchar opt_binary_and_compression
{ $$.set(&type_handler_medium_blob); } { $$.set(&type_handler_medium_blob, $3); }
| TINYTEXT opt_binary_and_compression | TINYTEXT opt_binary_and_compression
{ $$.set(&type_handler_tiny_blob); } { $$.set(&type_handler_tiny_blob, $2); }
| TEXT_SYM opt_field_length opt_binary_and_compression | TEXT_SYM opt_field_length opt_binary_and_compression
{ $$.set(&type_handler_blob, $2); } { $$.set(&type_handler_blob, $2, $3); }
| MEDIUMTEXT opt_binary_and_compression | MEDIUMTEXT opt_binary_and_compression
{ $$.set(&type_handler_medium_blob); } { $$.set(&type_handler_medium_blob, $2); }
| LONGTEXT opt_binary_and_compression | LONGTEXT opt_binary_and_compression
{ $$.set(&type_handler_long_blob); } { $$.set(&type_handler_long_blob, $2); }
| CLOB_ORACLE_SYM opt_binary_and_compression | CLOB_ORACLE_SYM opt_binary_and_compression
{ $$.set(&type_handler_long_blob); } { $$.set(&type_handler_long_blob, $2); }
| LONG_SYM opt_binary_and_compression | LONG_SYM opt_binary_and_compression
{ $$.set(&type_handler_medium_blob); } { $$.set(&type_handler_medium_blob, $2); }
| JSON_SYM opt_compressed | JSON_SYM opt_compressed
{ {
Lex->charset= &my_charset_utf8mb4_bin; $$.set(&type_handler_long_blob_json, &my_charset_utf8mb4_bin);
$$.set(&type_handler_long_blob_json);
} }
; ;
field_type_misc: field_type_misc:
ENUM '(' string_list ')' opt_binary ENUM '(' string_list ')' opt_binary
{ $$.set(&type_handler_enum); } { $$.set(&type_handler_enum, $5); }
| SET '(' string_list ')' opt_binary | SET '(' string_list ')' opt_binary
{ $$.set(&type_handler_set); } { $$.set(&type_handler_set, $5); }
; ;
char: char:
@@ -6272,35 +6276,38 @@ opt_precision:
attribute_list: attribute_list:
attribute_list attribute {} attribute_list attribute
{
if (($$= $1).merge_collate_clause_and_collate_clause($2))
MYSQL_YYABORT;
}
| attribute | attribute
; ;
attribute: attribute:
NULL_SYM { Lex->last_field->flags&= ~ NOT_NULL_FLAG; } NULL_SYM { Lex->last_field->flags&= ~ NOT_NULL_FLAG; $$.init(); }
| DEFAULT column_default_expr { Lex->last_field->default_value= $2; } | DEFAULT column_default_expr { Lex->last_field->default_value= $2; $$.init(); }
| ON UPDATE_SYM NOW_SYM opt_default_time_precision | ON UPDATE_SYM NOW_SYM opt_default_time_precision
{ {
Item *item= new (thd->mem_root) Item_func_now_local(thd, $4); Item *item= new (thd->mem_root) Item_func_now_local(thd, $4);
if (unlikely(item == NULL)) if (unlikely(item == NULL))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->last_field->on_update= item; Lex->last_field->on_update= item;
$$.init();
} }
| AUTO_INC { Lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; } | AUTO_INC { Lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; $$.init(); }
| SERIAL_SYM DEFAULT VALUE_SYM | SERIAL_SYM DEFAULT VALUE_SYM
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_KEY_FLAG; lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_KEY_FLAG;
lex->alter_info.flags|= ALTER_ADD_INDEX; lex->alter_info.flags|= ALTER_ADD_INDEX;
$$.init();
} }
| COLLATE_SYM collation_name | COLLATE_SYM collation_name
{ {
if (unlikely(Lex->charset && !my_charset_same(Lex->charset,$2))) $$.set_collate_exact($2);
my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0),
$2->coll_name.str, Lex->charset->cs_name.str));
Lex->last_field->charset= $2;
} }
| serial_attribute | serial_attribute { $$.init(); }
; ;
opt_compression_method: opt_compression_method:
@@ -6444,7 +6451,7 @@ collation_name:
} }
; ;
opt_collate: opt_collate_or_default:
/* empty */ { $$=NULL; } /* empty */ { $$=NULL; }
| COLLATE_SYM collation_name_or_default { $$=$2; } | COLLATE_SYM collation_name_or_default { $$=$2; }
; ;
@@ -6469,27 +6476,36 @@ charset_or_alias:
} }
; ;
collate: COLLATE_SYM collation_name_or_default { $$= $2; }
;
opt_binary: opt_binary:
/* empty */ { bincmp_collation(NULL, false); } /* empty */ { $$.init(); }
| binary {} | binary
; ;
binary: binary:
BYTE_SYM { bincmp_collation(&my_charset_bin, false); } BYTE_SYM { $$.set_charset(&my_charset_bin); }
| charset_or_alias opt_bin_mod { bincmp_collation($1, $2); } | charset_or_alias { $$.set_charset($1); }
| BINARY { bincmp_collation(NULL, true); } | charset_or_alias BINARY
| BINARY charset_or_alias { bincmp_collation($2, true); }
| charset_or_alias collate
{ {
if (!my_charset_same($2, $1)) if ($$.set_charset_collate_binary($1))
my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0), MYSQL_YYABORT;
$2->coll_name.str, $1->cs_name.str));
Lex->charset= $2;
} }
| collate { Lex->charset= $1; } | BINARY { $$.set_contextually_typed_binary_style(); }
| BINARY charset_or_alias
{
if ($$.set_charset_collate_binary($2))
MYSQL_YYABORT;
}
| charset_or_alias COLLATE_SYM DEFAULT
{
$$.set_charset_collate_default($1);
}
| charset_or_alias COLLATE_SYM collation_name
{
if ($$.set_charset_collate_exact($1, $3))
MYSQL_YYABORT;
}
| COLLATE_SYM collation_name { $$.set_collate_exact($2); }
| COLLATE_SYM DEFAULT { $$.set_collate_default(); }
; ;
opt_bin_mod: opt_bin_mod:
@@ -7559,7 +7575,8 @@ alter_list_item:
lex->alter_info.alter_rename_key_list.push_back(ak); lex->alter_info.alter_rename_key_list.push_back(ak);
lex->alter_info.flags|= ALTER_RENAME_INDEX; lex->alter_info.flags|= ALTER_RENAME_INDEX;
} }
| CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate | CONVERT_SYM TO_SYM charset charset_name_or_default
opt_collate_or_default
{ {
if (!$4) if (!$4)
{ {
@@ -9407,15 +9424,14 @@ opt_dyncol_type:
/* empty */ /* empty */
{ {
$$.set(DYN_COL_NULL); /* automatic type */ $$.set(DYN_COL_NULL); /* automatic type */
Lex->charset= NULL;
} }
| AS dyncol_type { $$= $2; } | AS dyncol_type { $$= $2; }
; ;
dyncol_type: dyncol_type:
numeric_dyncol_type { $$= $1; Lex->charset= NULL; } numeric_dyncol_type
| temporal_dyncol_type { $$= $1; Lex->charset= NULL; } | temporal_dyncol_type
| string_dyncol_type { $$= $1; } | string_dyncol_type
; ;
numeric_dyncol_type: numeric_dyncol_type:
@@ -9434,23 +9450,20 @@ temporal_dyncol_type:
; ;
string_dyncol_type: string_dyncol_type:
char char opt_binary
{ Lex->charset= thd->variables.collation_connection; }
opt_binary
{ {
$$.set(DYN_COL_STRING); if ($$.set(DYN_COL_STRING, $2, thd->variables.collation_connection))
MYSQL_YYABORT;
} }
| nchar | nchar
{ {
$$.set(DYN_COL_STRING); $$.set(DYN_COL_STRING, national_charset_info);
Lex->charset= national_charset_info;
} }
; ;
dyncall_create_element: dyncall_create_element:
expr ',' expr opt_dyncol_type expr ',' expr opt_dyncol_type
{ {
LEX *lex= Lex;
$$= (DYNCALL_CREATE_DEF *) $$= (DYNCALL_CREATE_DEF *)
alloc_root(thd->mem_root, sizeof(DYNCALL_CREATE_DEF)); alloc_root(thd->mem_root, sizeof(DYNCALL_CREATE_DEF));
if (unlikely($$ == NULL)) if (unlikely($$ == NULL))
@@ -9458,7 +9471,7 @@ dyncall_create_element:
$$->key= $1; $$->key= $1;
$$->value= $3; $$->value= $3;
$$->type= (DYNAMIC_COLUMN_TYPE)$4.dyncol_type(); $$->type= (DYNAMIC_COLUMN_TYPE)$4.dyncol_type();
$$->cs= lex->charset; $$->cs= $4.charset_collation();
if ($4.has_explicit_length()) if ($4.has_explicit_length())
$$->len= $4.length(); $$->len= $4.length();
else else
@@ -9597,8 +9610,7 @@ column_default_non_parenthesized_expr:
} }
| CAST_SYM '(' expr AS cast_type ')' | CAST_SYM '(' expr AS cast_type ')'
{ {
if (unlikely(!($$= $5.create_typecast_item_or_error(thd, $3, if (unlikely(!($$= $5.create_typecast_item_or_error(thd, $3))))
Lex->charset))))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| CASE_SYM when_list_opt_else END | CASE_SYM when_list_opt_else END
@@ -9614,8 +9626,7 @@ column_default_non_parenthesized_expr:
} }
| CONVERT_SYM '(' expr ',' cast_type ')' | CONVERT_SYM '(' expr ',' cast_type ')'
{ {
if (unlikely(!($$= $5.create_typecast_item_or_error(thd, $3, if (unlikely(!($$= $5.create_typecast_item_or_error(thd, $3))))
Lex->charset))))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| CONVERT_SYM '(' expr USING charset_name ')' | CONVERT_SYM '(' expr USING charset_name ')'
@@ -10151,9 +10162,8 @@ function_call_nonkeyword:
| |
COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')' COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')'
{ {
LEX *lex= Lex;
$$= create_func_dyncol_get(thd, $3, $5, $7.type_handler(), $$= create_func_dyncol_get(thd, $3, $5, $7.type_handler(),
$7, lex->charset); $7, $7.charset());
if (unlikely($$ == NULL)) if (unlikely($$ == NULL))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
@@ -11054,26 +11064,31 @@ in_sum_expr:
cast_type: cast_type:
BINARY opt_field_length BINARY opt_field_length
{ $$.set(&type_handler_long_blob, $2); Lex->charset= &my_charset_bin; } { $$.set(&type_handler_long_blob, $2, &my_charset_bin); }
| CHAR_SYM opt_field_length | CHAR_SYM opt_field_length opt_binary
{ Lex->charset= thd->variables.collation_connection; } {
opt_binary if ($$.set(&type_handler_long_blob, $2, $3,
{ $$.set(&type_handler_long_blob, $2); } thd->variables.collation_connection))
| VARCHAR field_length MYSQL_YYABORT;
{ Lex->charset= thd->variables.collation_connection; } }
opt_binary | VARCHAR field_length opt_binary
{ $$.set(&type_handler_long_blob, $2); } {
| VARCHAR2_ORACLE_SYM field_length if ($$.set(&type_handler_long_blob, $2, $3,
{ Lex->charset= thd->variables.collation_connection; } thd->variables.collation_connection))
opt_binary MYSQL_YYABORT;
{ $$.set(&type_handler_long_blob, $2); } }
| VARCHAR2_ORACLE_SYM field_length opt_binary
{
if ($$.set(&type_handler_long_blob, $2, $3,
thd->variables.collation_connection))
MYSQL_YYABORT;
}
| NCHAR_SYM opt_field_length | NCHAR_SYM opt_field_length
{ {
Lex->charset= national_charset_info; $$.set(&type_handler_long_blob, $2, national_charset_info);
$$.set(&type_handler_long_blob, $2);
} }
| cast_type_numeric { $$= $1; Lex->charset= NULL; } | cast_type_numeric { $$= $1; }
| cast_type_temporal { $$= $1; Lex->charset= NULL; } | cast_type_temporal { $$= $1; }
| IDENT_sys | IDENT_sys
{ {
if (Lex->set_cast_type_udt(&$$, $1)) if (Lex->set_cast_type_udt(&$$, $1))
@@ -11262,7 +11277,7 @@ json_table_column:
!lex->json_table->m_cur_json_table_column)) !lex->json_table->m_cur_json_table_column))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->init_last_field(f, &$1, NULL); lex->init_last_field(f, &$1);
} }
json_table_column_type json_table_column_type
{ {
@@ -11293,7 +11308,7 @@ json_table_column_type:
{ {
Lex_field_type_st type; Lex_field_type_st type;
type.set(&type_handler_slong); type.set(&type_handler_slong);
Lex->last_field->set_attributes(thd, type, Lex->charset, Lex->last_field->set_attributes(thd, type,
COLUMN_DEFINITION_TABLE_FIELD); COLUMN_DEFINITION_TABLE_FIELD);
Lex->json_table->m_cur_json_table_column-> Lex->json_table->m_cur_json_table_column->
set(Json_table_column::FOR_ORDINALITY); set(Json_table_column::FOR_ORDINALITY);
@@ -11301,20 +11316,23 @@ json_table_column_type:
| json_table_field_type PATH_SYM json_text_literal | json_table_field_type PATH_SYM json_text_literal
json_opt_on_empty_or_error json_opt_on_empty_or_error
{ {
Lex->last_field->set_attributes(thd, $1, Lex->charset, Lex->last_field->set_attributes(thd, $1,
COLUMN_DEFINITION_TABLE_FIELD); COLUMN_DEFINITION_TABLE_FIELD);
if (Lex->json_table->m_cur_json_table_column-> if (Lex->json_table->m_cur_json_table_column->
set(thd, Json_table_column::PATH, $3, Lex->charset)) set(thd, Json_table_column::PATH, $3,
$1.lex_charset_collation()))
{ {
MYSQL_YYABORT; MYSQL_YYABORT;
} }
} }
| json_table_field_type EXISTS PATH_SYM json_text_literal | json_table_field_type EXISTS PATH_SYM json_text_literal
{ {
Lex->last_field->set_attributes(thd, $1, Lex->charset, Lex->last_field->set_attributes(thd, $1,
COLUMN_DEFINITION_TABLE_FIELD); COLUMN_DEFINITION_TABLE_FIELD);
Lex->json_table->m_cur_json_table_column-> if (Lex->json_table->m_cur_json_table_column->
set(thd, Json_table_column::EXISTS_PATH, $4, Lex->charset); set(thd, Json_table_column::EXISTS_PATH, $4,
$1.lex_charset_collation()))
MYSQL_YYABORT;
} }
; ;
@@ -16484,7 +16502,7 @@ option_value_no_option_type:
thd->parse_error(); thd->parse_error();
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| NAMES_SYM charset_name_or_default opt_collate | NAMES_SYM charset_name_or_default opt_collate_or_default
{ {
if (sp_create_assignment_lex(thd, $1.pos())) if (sp_create_assignment_lex(thd, $1.pos()))
MYSQL_YYABORT; MYSQL_YYABORT;
@@ -17716,8 +17734,7 @@ sf_return_type:
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->init_last_field(&lex->sphead->m_return_field_def, lex->init_last_field(&lex->sphead->m_return_field_def,
&empty_clex_str, &empty_clex_str);
thd->variables.collation_database);
} }
field_type field_type
{ {

View File

@@ -28,6 +28,7 @@
#include "my_base.h" /* ha_rows, ha_key_alg */ #include "my_base.h" /* ha_rows, ha_key_alg */
#include <mysql_com.h> /* USERNAME_LENGTH */ #include <mysql_com.h> /* USERNAME_LENGTH */
#include "sql_bitmap.h" #include "sql_bitmap.h"
#include "lex_charset.h"
struct TABLE; struct TABLE;
class Type_handler; class Type_handler;
@@ -601,18 +602,24 @@ public:
struct Lex_length_and_dec_st struct Lex_length_and_dec_st
{ {
private: protected:
uint32 m_length; uint32 m_length;
uint8 m_dec; uint8 m_dec;
uint8 m_collation_type:LEX_CHARSET_COLLATION_TYPE_BITS;
bool m_has_explicit_length:1; bool m_has_explicit_length:1;
bool m_has_explicit_dec:1; bool m_has_explicit_dec:1;
bool m_length_overflowed:1; bool m_length_overflowed:1;
bool m_dec_overflowed:1; bool m_dec_overflowed:1;
static_assert(LEX_CHARSET_COLLATION_TYPE_BITS <= 8,
"Lex_length_and_dec_st::m_collation_type bits check");
public: public:
void reset() void reset()
{ {
m_length= 0; m_length= 0;
m_dec= 0; m_dec= 0;
m_collation_type= 0;
m_has_explicit_length= false; m_has_explicit_length= false;
m_has_explicit_dec= false; m_has_explicit_dec= false;
m_length_overflowed= false; m_length_overflowed= false;
@@ -622,6 +629,7 @@ public:
{ {
m_length= length; m_length= length;
m_dec= 0; m_dec= 0;
m_collation_type= 0;
m_has_explicit_length= true; m_has_explicit_length= true;
m_has_explicit_dec= false; m_has_explicit_dec= false;
m_length_overflowed= false; m_length_overflowed= false;
@@ -631,6 +639,7 @@ public:
{ {
m_length= 0; m_length= 0;
m_dec= dec; m_dec= dec;
m_collation_type= 0;
m_has_explicit_length= false; m_has_explicit_length= false;
m_has_explicit_dec= true; m_has_explicit_dec= true;
m_length_overflowed= false; m_length_overflowed= false;
@@ -640,6 +649,7 @@ public:
{ {
m_length= length; m_length= length;
m_dec= dec; m_dec= dec;
m_collation_type= 0;
m_has_explicit_length= true; m_has_explicit_length= true;
m_has_explicit_dec= true; m_has_explicit_dec= true;
m_length_overflowed= false; m_length_overflowed= false;
@@ -677,30 +687,59 @@ struct Lex_field_type_st: public Lex_length_and_dec_st
{ {
private: private:
const Type_handler *m_handler; const Type_handler *m_handler;
CHARSET_INFO *m_ci;
public: public:
void set(const Type_handler *handler, Lex_length_and_dec_st length_and_dec) void set(const Type_handler *handler,
Lex_length_and_dec_st length_and_dec,
CHARSET_INFO *cs= NULL)
{ {
m_handler= handler; m_handler= handler;
m_ci= cs;
Lex_length_and_dec_st::operator=(length_and_dec); Lex_length_and_dec_st::operator=(length_and_dec);
} }
void set(const Type_handler *handler,
const Lex_length_and_dec_st &length_and_dec,
const Lex_charset_collation_st &coll)
{
m_handler= handler;
m_ci= coll.charset_collation();
Lex_length_and_dec_st::operator=(length_and_dec);
m_collation_type= ((uint8) coll.type()) & 0x3;
}
void set(const Type_handler *handler, const Lex_charset_collation_st &coll)
{
m_handler= handler;
m_ci= coll.charset_collation();
Lex_length_and_dec_st::reset();
m_collation_type= ((uint8) coll.type()) & 0x3;
}
void set(const Type_handler *handler, CHARSET_INFO *cs= NULL)
{
m_handler= handler;
m_ci= cs;
Lex_length_and_dec_st::reset();
}
void set_handler_length_flags(const Type_handler *handler, void set_handler_length_flags(const Type_handler *handler,
const Lex_length_and_dec_st &length, const Lex_length_and_dec_st &length,
uint32 flags); uint32 flags);
void set_handler_length(const Type_handler *handler, uint32 length) void set_handler_length(const Type_handler *handler, uint32 length)
{ {
m_handler= handler; m_handler= handler;
m_ci= NULL;
Lex_length_and_dec_st::set_length_only(length); Lex_length_and_dec_st::set_length_only(length);
} }
void set(const Type_handler *handler)
{
m_handler= handler;
Lex_length_and_dec_st::reset();
}
void set_handler(const Type_handler *handler) void set_handler(const Type_handler *handler)
{ {
m_handler= handler; m_handler= handler;
} }
const Type_handler *type_handler() const { return m_handler; } const Type_handler *type_handler() const { return m_handler; }
CHARSET_INFO *charset_collation() const { return m_ci; }
Lex_charset_collation lex_charset_collation() const
{
return Lex_charset_collation(m_ci,
(Lex_charset_collation_st::Type)
m_collation_type);
}
}; };
@@ -708,18 +747,38 @@ struct Lex_dyncol_type_st: public Lex_length_and_dec_st
{ {
private: private:
int m_type; // enum_dynamic_column_type is not visible here, so use int int m_type; // enum_dynamic_column_type is not visible here, so use int
CHARSET_INFO *m_ci;
public: public:
void set(int type, Lex_length_and_dec_st length_and_dec) void set(int type, Lex_length_and_dec_st length_and_dec,
CHARSET_INFO *cs= NULL)
{ {
m_type= type; m_type= type;
m_ci= cs;
Lex_length_and_dec_st::operator=(length_and_dec); Lex_length_and_dec_st::operator=(length_and_dec);
} }
void set(int type) void set(int type)
{ {
m_type= type; m_type= type;
m_ci= NULL;
Lex_length_and_dec_st::reset(); Lex_length_and_dec_st::reset();
} }
void set(int type, CHARSET_INFO *cs)
{
m_type= type;
m_ci= cs;
Lex_length_and_dec_st::reset();
}
bool set(int type, const Lex_charset_collation_st &collation,
CHARSET_INFO *charset)
{
CHARSET_INFO *tmp= collation.resolved_to_character_set(charset);
if (!tmp)
return true;
set(type, tmp);
return false;
}
int dyncol_type() const { return m_type; } int dyncol_type() const { return m_type; }
CHARSET_INFO *charset_collation() const { return m_ci; }
}; };

View File

@@ -630,3 +630,7 @@ struct charset_info_st my_charset_bin =
&my_charset_handler, &my_charset_handler,
&my_collation_binary_handler &my_collation_binary_handler
}; };
struct charset_info_st my_collation_contextually_typed_binary= {0};
struct charset_info_st my_collation_contextually_typed_default= {0};