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(PART_KEY);
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);
#undef ff2s_check_flag
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_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_UTF8MB4 "utf8mb4"

View File

@@ -180,7 +180,7 @@ enum enum_indicator_type
#define NUM_FLAG 32768U /* Field is num (for clients) */
#define PART_KEY_FLAG 16384U /* Intern; Part of some key */
#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 FIELD_IN_PART_FUNC_FLAG (1U << 19)/* Field part of partition func */
#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/compat56.cc
../sql/sql_schema.cc
../sql/lex_charset.cc
../sql/sql_type.cc ../sql/sql_type.h
../sql/sql_mode.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
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
#
#
@@ -8950,3 +8982,31 @@ Warning 1292 Truncated incorrect INTEGER value: 'a
#
# 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;
--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 # End of 10.2 tests
--echo #
@@ -475,3 +497,29 @@ SELECT CAST(_latin1 0x61FF62 AS INT);
--echo #
--echo # End of 10.5 tests
--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
#
#
# 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 # End of 10.5 tests
--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
😎
#
# 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
#
#
@@ -4167,3 +4199,31 @@ ERROR 42000: COLLATION 'latin1_swedish_ci' is not valid for CHARACTER SET 'utf8m
#
# 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 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 # End of 10.2 tests
--echo #
@@ -2062,3 +2083,30 @@ SELECT 1 COLLATE latin1_swedish_ci;
--echo #
--echo # End of 10.5 tests
--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
#
#
# 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 # End of 10.6 tests
--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;
drop role test_role;
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
after is_role;
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 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
after is_role;
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_master_ack_receiver.cc
sql_schema.cc
lex_charset.cc
sql_type.cc sql_mode.cc sql_type_json.cc
sql_type_string.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,
const Lex_field_type_st &def,
CHARSET_INFO *cs,
column_definition_type_t type)
{
DBUG_ASSERT(type_handler() == &type_handler_null);
DBUG_ASSERT(charset == &my_charset_bin || charset == NULL);
DBUG_ASSERT(length == 0);
DBUG_ASSERT(decimals == 0);
set_handler(def.type_handler());
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);
bool set_attributes(THD *thd,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type);
void create_length_to_internal_length_null()
{
@@ -5493,6 +5492,24 @@ public:
{ return compression_method_ptr; }
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:
const Type_handler *m_type_handler;
CHARSET_INFO *m_charset;
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_charset= cs;
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)
{
m_type_handler= handler;
m_charset= NULL;
Lex_length_and_dec_st::reset();
}
const Type_handler *type_handler() const { return m_type_handler; }
Item *create_typecast_item(THD *thd, Item *item,
CHARSET_INFO *cs= NULL) const
CHARSET_INFO *charset() const { return m_charset; }
Item *create_typecast_item(THD *thd, Item *item) const
{
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,
CHARSET_INFO *cs= NULL) const;
Item *create_typecast_item_or_error(THD *thd, Item *item) const;
};

View File

@@ -716,7 +716,7 @@ bool Create_json_table::add_json_table_fields(THD *thd, TABLE *table,
uint fieldnr= 0;
MEM_ROOT *mem_root_save= thd->mem_root;
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");
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.
*/
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,
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)
{
return str->append('\'') ||
@@ -915,7 +926,10 @@ int Json_table_column::print(THD *thd, Field **f, String *str)
if (str->append(column_type) ||
((*f)->has_charset() && m_explicit_cs &&
(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) ||
print_path(str, &m_path))
return 1;

View File

@@ -160,6 +160,8 @@ public:
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,
const Lex_charset_collation_st &cl);
Json_table_column(Create_field *f, Json_table_nested_path *nest) :
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,
const LEX_CSTRING *field_name,
const CHARSET_INFO *cs)
const LEX_CSTRING *field_name)
{
last_field= field;
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;
}
sp_variable *spvar= spcont->add_variable(thd, name);
init_last_field(&spvar->field_def, name,
thd->variables.collation_database);
init_last_field(&spvar->field_def, name);
return spvar;
}
@@ -6402,8 +6375,7 @@ bool LEX::sp_param_fill_definition(sp_variable *spvar,
const Lex_field_type_st &def)
{
return
last_field->set_attributes(thd, def, charset,
COLUMN_DEFINITION_ROUTINE_PARAM) ||
last_field->set_attributes(thd, def, COLUMN_DEFINITION_ROUTINE_PARAM) ||
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)
{
return
last_field->set_attributes(thd, def, charset,
COLUMN_DEFINITION_FUNCTION_RETURN) ||
last_field->set_attributes(thd, def, COLUMN_DEFINITION_FUNCTION_RETURN) ||
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);
spcont->declare_var_boundary(nvars);
thd->lex->init_last_field(&spvar->field_def, &spvar->name,
thd->variables.collation_database);
thd->lex->init_last_field(&spvar->field_def, &spvar->name);
}
@@ -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())))
return NULL;
init_last_field(res, &name, thd->variables.collation_database);
init_last_field(res, &name);
return res;
}
Item *
Lex_cast_type_st::create_typecast_item_or_error(THD *thd, Item *item,
CHARSET_INFO *cs) const
Lex_cast_type_st::create_typecast_item_or_error(THD *thd, Item *item) const
{
Item *tmp= create_typecast_item(thd, item, cs);
Item *tmp= create_typecast_item(thd, item);
if (!tmp)
{
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;
if (!(h= Type_handler::handler_by_name_or_error(thd, name)))
return true;
type->set(h, attr);
charset= &my_charset_bin;
type->set(h, attr, &my_charset_bin);
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)))
return true;
type->set(h);
charset= NULL;
return false;
}

View File

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

View File

@@ -10463,24 +10463,6 @@ merge_charset_and_collation(CHARSET_INFO *cs, CHARSET_INFO *cl)
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()
{
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 check_ident_length(const LEX_CSTRING *ident);
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_identifier_name(LEX_CSTRING *str, uint max_char_length,
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::
prepare_charset_for_string(const Column_derived_attributes *dattr)
{
if (!charset)
charset= dattr->charset();
return (flags & BINCMP_FLAG) && !(charset= find_bin_collation(charset));
CHARSET_INFO *tmp= lex_charset_collation().
resolved_to_character_set(dattr->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)
{
DBUG_ASSERT(charset);
const Column_derived_attributes dattr(&my_charset_bin);
const Column_derived_attributes dattr(thd->variables.collation_database);
return prepare_stage1(thd, mem_root, NULL, HA_CAN_GEOMETRY, &dattr) ||
prepare_stage2(NULL, HA_CAN_GEOMETRY);
}

View File

@@ -2713,11 +2713,10 @@ bool
Type_handler::Column_definition_set_attributes(THD *thd,
Column_definition *def,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type)
const
{
def->charset= cs;
def->set_lex_charset_collation(attr.lex_charset_collation());
def->set_length_and_dec(attr);
return false;
}
@@ -2746,11 +2745,10 @@ Type_handler_string::Column_definition_set_attributes(
THD *thd,
Column_definition *def,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
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 (attr.has_explicit_length())
return false;
switch (type) {
@@ -2778,11 +2776,10 @@ Type_handler_varchar::Column_definition_set_attributes(
THD *thd,
Column_definition *def,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
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 (attr.has_explicit_length())
return false;
switch (type) {
@@ -3156,7 +3153,7 @@ bool Type_handler_general_purpose_string::
Change character sets for all varchar/char/text 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();
return false;
};
@@ -4267,10 +4264,9 @@ Type_handler_timestamp_common::
Column_definition_set_attributes(THD *thd,
Column_definition *def,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
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)
def->flags|= NOT_NULL_FLAG;
return false;

View File

@@ -3924,7 +3924,6 @@ public:
virtual bool Column_definition_set_attributes(THD *thd,
Column_definition *def,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type)
const;
// Fix attributes after the parser
@@ -6659,7 +6658,6 @@ public:
bool Column_definition_set_attributes(THD *thd,
Column_definition *def,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type)
const override;
};
@@ -6912,7 +6910,6 @@ public:
bool Column_definition_set_attributes(THD *thd,
Column_definition *def,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type)
const override;
bool Column_definition_fix_attributes(Column_definition *c) const override;
@@ -7009,7 +7006,6 @@ public:
bool Column_definition_set_attributes(THD *thd,
Column_definition *def,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type)
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
#define bincmp_collation(X,Y) \
do \
{ \
if (unlikely(Lex->set_bincmp(X,Y))) \
MYSQL_YYABORT; \
} while(0)
%}
%union {
int num;
@@ -221,6 +213,7 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)()
Lex_length_and_dec_st Lex_length_and_dec;
Lex_cast_type_st Lex_cast_type;
Lex_field_type_st Lex_field_type;
Lex_charset_collation_st Lex_charset_collation;
Lex_dyncol_type_st Lex_dyncol_type;
Lex_for_loop_st for_loop;
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
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
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
%type <charset>
opt_collate
collate
opt_collate_or_default
charset_name
charset_or_alias
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
no_braces_with_names opt_values_with_names values_with_names
procedure_list procedure_list2 procedure_item
field_def handler opt_generated_always
handler opt_generated_always
opt_ignore opt_column opt_restrict
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
opt_delete_options opt_delete_option varchar nchar nvarchar
opt_outer table_list table_name table_alias_ref_list table_alias_ref
attribute attribute_list
compressed_deprecated_data_type_attribute
compressed_deprecated_column_attribute
grant_list
@@ -3124,7 +3124,7 @@ optionally_qualified_column_ident:
row_field_definition:
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);
}
;
@@ -3157,7 +3157,7 @@ sp_decl_variable_list:
sp_decl_idents_init_vars
field_type
{
Lex->last_field->set_attributes(thd, $2, Lex->charset,
Lex->last_field->set_attributes(thd, $2,
COLUMN_DEFINITION_ROUTINE_LOCAL);
}
sp_opt_default
@@ -5723,7 +5723,7 @@ field_spec:
if (unlikely(!f))
MYSQL_YYABORT;
lex->init_last_field(f, &$1, NULL);
lex->init_last_field(f, &$1);
$<create_field>$= f;
lex->parsing_options.lookup_keywords_after_qualifier= true;
}
@@ -5751,10 +5751,16 @@ field_spec:
field_type_or_serial:
qualified_field_type
{
Lex->last_field->set_attributes(thd, $1, Lex->charset,
Lex->last_field->set_attributes(thd, $1,
COLUMN_DEFINITION_TABLE_FIELD);
}
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
{
Lex->last_field->set_handler(&type_handler_ulonglong);
@@ -5786,25 +5792,34 @@ opt_asrow_attribute_list:
;
field_def:
/* empty */ { }
/* empty */ { $$.init(); }
| attribute_list
| attribute_list compressed_deprecated_column_attribute
| attribute_list compressed_deprecated_column_attribute { $$= $1; }
| 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
{
Lex->last_field->vcol_info= $3;
Lex->last_field->flags&= ~NOT_NULL_FLAG; // undo automatic NOT NULL for timestamps
}
vcol_opt_specifier vcol_opt_attribute
{
$$.init();
}
| opt_generated_always AS ROW_SYM START_SYM opt_asrow_attribute
{
if (Lex->last_field_generated_always_as_row_start())
MYSQL_YYABORT;
$$.init();
}
| opt_generated_always AS ROW_SYM END opt_asrow_attribute
{
if (Lex->last_field_generated_always_as_row_end())
MYSQL_YYABORT;
$$.init();
}
;
@@ -6017,49 +6032,46 @@ field_type_numeric:
opt_binary_and_compression:
/* empty */
| binary
| binary compressed_deprecated_data_type_attribute
| compressed opt_binary
/* empty */ { $$.init(); }
| binary { $$= $1; }
| binary compressed_deprecated_data_type_attribute { $$= $1; }
| compressed opt_binary { $$= $2; }
;
field_type_string:
char opt_field_length opt_binary
{
$$.set(&type_handler_string, $2);
$$.set(&type_handler_string, $2, $3);
}
| nchar opt_field_length opt_bin_mod
{
$$.set(&type_handler_string, $2);
bincmp_collation(national_charset_info, $3);
$$.set(&type_handler_string, $2,
Lex_charset_collation::national($3));
}
| BINARY opt_field_length
{
Lex->charset=&my_charset_bin;
$$.set(&type_handler_string, $2);
$$.set(&type_handler_string, $2, &my_charset_bin);
}
| 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
{
$$.set(&type_handler_varchar, $2);
$$.set(&type_handler_varchar, $2, $3);
}
| nvarchar opt_field_length opt_compressed opt_bin_mod
{
$$.set(&type_handler_varchar, $2);
bincmp_collation(national_charset_info, $4);
$$.set(&type_handler_varchar, $2,
Lex_charset_collation::national($4));
}
| VARBINARY opt_field_length opt_compressed
{
Lex->charset=&my_charset_bin;
$$.set(&type_handler_varchar, $2);
$$.set(&type_handler_varchar, $2, &my_charset_bin);
}
| RAW_ORACLE_SYM opt_field_length opt_compressed
{
Lex->charset= &my_charset_bin;
$$.set(&type_handler_varchar, $2);
$$.set(&type_handler_varchar, $2, &my_charset_bin);
}
;
@@ -6105,65 +6117,57 @@ field_type_temporal:
field_type_lob:
TINYBLOB opt_compressed
{
Lex->charset=&my_charset_bin;
$$.set(&type_handler_tiny_blob);
$$.set(&type_handler_tiny_blob, &my_charset_bin);
}
| BLOB_MARIADB_SYM opt_field_length opt_compressed
{
Lex->charset=&my_charset_bin;
$$.set(&type_handler_blob, $2);
$$.set(&type_handler_blob, $2, &my_charset_bin);
}
| BLOB_ORACLE_SYM field_length opt_compressed
{
Lex->charset=&my_charset_bin;
$$.set(&type_handler_blob, $2);
$$.set(&type_handler_blob, $2, &my_charset_bin);
}
| BLOB_ORACLE_SYM opt_compressed
{
Lex->charset=&my_charset_bin;
$$.set(&type_handler_long_blob);
$$.set(&type_handler_long_blob, &my_charset_bin);
}
| MEDIUMBLOB opt_compressed
{
Lex->charset=&my_charset_bin;
$$.set(&type_handler_medium_blob);
$$.set(&type_handler_medium_blob, &my_charset_bin);
}
| LONGBLOB opt_compressed
{
Lex->charset=&my_charset_bin;
$$.set(&type_handler_long_blob);
$$.set(&type_handler_long_blob, &my_charset_bin);
}
| LONG_SYM VARBINARY opt_compressed
{
Lex->charset=&my_charset_bin;
$$.set(&type_handler_medium_blob);
$$.set(&type_handler_medium_blob, &my_charset_bin);
}
| LONG_SYM varchar opt_binary_and_compression
{ $$.set(&type_handler_medium_blob); }
{ $$.set(&type_handler_medium_blob, $3); }
| 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
{ $$.set(&type_handler_blob, $2); }
{ $$.set(&type_handler_blob, $2, $3); }
| MEDIUMTEXT opt_binary_and_compression
{ $$.set(&type_handler_medium_blob); }
{ $$.set(&type_handler_medium_blob, $2); }
| LONGTEXT opt_binary_and_compression
{ $$.set(&type_handler_long_blob); }
{ $$.set(&type_handler_long_blob, $2); }
| CLOB_ORACLE_SYM opt_binary_and_compression
{ $$.set(&type_handler_long_blob); }
{ $$.set(&type_handler_long_blob, $2); }
| LONG_SYM opt_binary_and_compression
{ $$.set(&type_handler_medium_blob); }
{ $$.set(&type_handler_medium_blob, $2); }
| JSON_SYM opt_compressed
{
Lex->charset= &my_charset_utf8mb4_bin;
$$.set(&type_handler_long_blob_json);
$$.set(&type_handler_long_blob_json, &my_charset_utf8mb4_bin);
}
;
field_type_misc:
ENUM '(' string_list ')' opt_binary
{ $$.set(&type_handler_enum); }
{ $$.set(&type_handler_enum, $5); }
| SET '(' string_list ')' opt_binary
{ $$.set(&type_handler_set); }
{ $$.set(&type_handler_set, $5); }
;
char:
@@ -6272,35 +6276,38 @@ opt_precision:
attribute_list:
attribute_list attribute {}
attribute_list attribute
{
if (($$= $1).merge_collate_clause_and_collate_clause($2))
MYSQL_YYABORT;
}
| attribute
;
attribute:
NULL_SYM { Lex->last_field->flags&= ~ NOT_NULL_FLAG; }
| DEFAULT column_default_expr { Lex->last_field->default_value= $2; }
NULL_SYM { Lex->last_field->flags&= ~ NOT_NULL_FLAG; $$.init(); }
| DEFAULT column_default_expr { Lex->last_field->default_value= $2; $$.init(); }
| ON UPDATE_SYM NOW_SYM opt_default_time_precision
{
Item *item= new (thd->mem_root) Item_func_now_local(thd, $4);
if (unlikely(item == NULL))
MYSQL_YYABORT;
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
{
LEX *lex=Lex;
lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_KEY_FLAG;
lex->alter_info.flags|= ALTER_ADD_INDEX;
$$.init();
}
| COLLATE_SYM collation_name
{
if (unlikely(Lex->charset && !my_charset_same(Lex->charset,$2)))
my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0),
$2->coll_name.str, Lex->charset->cs_name.str));
Lex->last_field->charset= $2;
$$.set_collate_exact($2);
}
| serial_attribute
| serial_attribute { $$.init(); }
;
opt_compression_method:
@@ -6444,7 +6451,7 @@ collation_name:
}
;
opt_collate:
opt_collate_or_default:
/* empty */ { $$=NULL; }
| COLLATE_SYM collation_name_or_default { $$=$2; }
;
@@ -6469,27 +6476,36 @@ charset_or_alias:
}
;
collate: COLLATE_SYM collation_name_or_default { $$= $2; }
;
opt_binary:
/* empty */ { bincmp_collation(NULL, false); }
| binary {}
/* empty */ { $$.init(); }
| binary
;
binary:
BYTE_SYM { bincmp_collation(&my_charset_bin, false); }
| charset_or_alias opt_bin_mod { bincmp_collation($1, $2); }
| BINARY { bincmp_collation(NULL, true); }
| BINARY charset_or_alias { bincmp_collation($2, true); }
| charset_or_alias collate
BYTE_SYM { $$.set_charset(&my_charset_bin); }
| charset_or_alias { $$.set_charset($1); }
| charset_or_alias BINARY
{
if (!my_charset_same($2, $1))
my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0),
$2->coll_name.str, $1->cs_name.str));
Lex->charset= $2;
if ($$.set_charset_collate_binary($1))
MYSQL_YYABORT;
}
| 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:
@@ -7559,7 +7575,8 @@ alter_list_item:
lex->alter_info.alter_rename_key_list.push_back(ak);
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)
{
@@ -9407,15 +9424,14 @@ opt_dyncol_type:
/* empty */
{
$$.set(DYN_COL_NULL); /* automatic type */
Lex->charset= NULL;
}
| AS dyncol_type { $$= $2; }
;
dyncol_type:
numeric_dyncol_type { $$= $1; Lex->charset= NULL; }
| temporal_dyncol_type { $$= $1; Lex->charset= NULL; }
| string_dyncol_type { $$= $1; }
numeric_dyncol_type
| temporal_dyncol_type
| string_dyncol_type
;
numeric_dyncol_type:
@@ -9434,23 +9450,20 @@ temporal_dyncol_type:
;
string_dyncol_type:
char
{ Lex->charset= thd->variables.collation_connection; }
opt_binary
char opt_binary
{
$$.set(DYN_COL_STRING);
if ($$.set(DYN_COL_STRING, $2, thd->variables.collation_connection))
MYSQL_YYABORT;
}
| nchar
{
$$.set(DYN_COL_STRING);
Lex->charset= national_charset_info;
$$.set(DYN_COL_STRING, national_charset_info);
}
;
dyncall_create_element:
expr ',' expr opt_dyncol_type
{
LEX *lex= Lex;
$$= (DYNCALL_CREATE_DEF *)
alloc_root(thd->mem_root, sizeof(DYNCALL_CREATE_DEF));
if (unlikely($$ == NULL))
@@ -9458,7 +9471,7 @@ dyncall_create_element:
$$->key= $1;
$$->value= $3;
$$->type= (DYNAMIC_COLUMN_TYPE)$4.dyncol_type();
$$->cs= lex->charset;
$$->cs= $4.charset_collation();
if ($4.has_explicit_length())
$$->len= $4.length();
else
@@ -9597,8 +9610,7 @@ column_default_non_parenthesized_expr:
}
| CAST_SYM '(' expr AS cast_type ')'
{
if (unlikely(!($$= $5.create_typecast_item_or_error(thd, $3,
Lex->charset))))
if (unlikely(!($$= $5.create_typecast_item_or_error(thd, $3))))
MYSQL_YYABORT;
}
| CASE_SYM when_list_opt_else END
@@ -9614,8 +9626,7 @@ column_default_non_parenthesized_expr:
}
| CONVERT_SYM '(' expr ',' cast_type ')'
{
if (unlikely(!($$= $5.create_typecast_item_or_error(thd, $3,
Lex->charset))))
if (unlikely(!($$= $5.create_typecast_item_or_error(thd, $3))))
MYSQL_YYABORT;
}
| CONVERT_SYM '(' expr USING charset_name ')'
@@ -10151,9 +10162,8 @@ function_call_nonkeyword:
|
COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')'
{
LEX *lex= Lex;
$$= create_func_dyncol_get(thd, $3, $5, $7.type_handler(),
$7, lex->charset);
$7, $7.charset());
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
@@ -11054,26 +11064,31 @@ in_sum_expr:
cast_type:
BINARY opt_field_length
{ $$.set(&type_handler_long_blob, $2); Lex->charset= &my_charset_bin; }
| CHAR_SYM opt_field_length
{ Lex->charset= thd->variables.collation_connection; }
opt_binary
{ $$.set(&type_handler_long_blob, $2); }
| VARCHAR field_length
{ Lex->charset= thd->variables.collation_connection; }
opt_binary
{ $$.set(&type_handler_long_blob, $2); }
| VARCHAR2_ORACLE_SYM field_length
{ Lex->charset= thd->variables.collation_connection; }
opt_binary
{ $$.set(&type_handler_long_blob, $2); }
{ $$.set(&type_handler_long_blob, $2, &my_charset_bin); }
| CHAR_SYM opt_field_length opt_binary
{
if ($$.set(&type_handler_long_blob, $2, $3,
thd->variables.collation_connection))
MYSQL_YYABORT;
}
| VARCHAR field_length opt_binary
{
if ($$.set(&type_handler_long_blob, $2, $3,
thd->variables.collation_connection))
MYSQL_YYABORT;
}
| 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
{
Lex->charset= national_charset_info;
$$.set(&type_handler_long_blob, $2);
$$.set(&type_handler_long_blob, $2, national_charset_info);
}
| cast_type_numeric { $$= $1; Lex->charset= NULL; }
| cast_type_temporal { $$= $1; Lex->charset= NULL; }
| cast_type_numeric { $$= $1; }
| cast_type_temporal { $$= $1; }
| IDENT_sys
{
if (Lex->set_cast_type_udt(&$$, $1))
@@ -11262,7 +11277,7 @@ json_table_column:
!lex->json_table->m_cur_json_table_column))
MYSQL_YYABORT;
lex->init_last_field(f, &$1, NULL);
lex->init_last_field(f, &$1);
}
json_table_column_type
{
@@ -11293,7 +11308,7 @@ json_table_column_type:
{
Lex_field_type_st type;
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);
Lex->json_table->m_cur_json_table_column->
set(Json_table_column::FOR_ORDINALITY);
@@ -11301,20 +11316,23 @@ json_table_column_type:
| json_table_field_type PATH_SYM json_text_literal
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);
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;
}
}
| 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);
Lex->json_table->m_cur_json_table_column->
set(thd, Json_table_column::EXISTS_PATH, $4, Lex->charset);
if (Lex->json_table->m_cur_json_table_column->
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();
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()))
MYSQL_YYABORT;
@@ -17716,8 +17734,7 @@ sf_return_type:
{
LEX *lex= Lex;
lex->init_last_field(&lex->sphead->m_return_field_def,
&empty_clex_str,
thd->variables.collation_database);
&empty_clex_str);
}
field_type
{

View File

@@ -28,6 +28,7 @@
#include "my_base.h" /* ha_rows, ha_key_alg */
#include <mysql_com.h> /* USERNAME_LENGTH */
#include "sql_bitmap.h"
#include "lex_charset.h"
struct TABLE;
class Type_handler;
@@ -601,18 +602,24 @@ public:
struct Lex_length_and_dec_st
{
private:
protected:
uint32 m_length;
uint8 m_dec;
uint8 m_collation_type:LEX_CHARSET_COLLATION_TYPE_BITS;
bool m_has_explicit_length:1;
bool m_has_explicit_dec:1;
bool m_length_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:
void reset()
{
m_length= 0;
m_dec= 0;
m_collation_type= 0;
m_has_explicit_length= false;
m_has_explicit_dec= false;
m_length_overflowed= false;
@@ -622,6 +629,7 @@ public:
{
m_length= length;
m_dec= 0;
m_collation_type= 0;
m_has_explicit_length= true;
m_has_explicit_dec= false;
m_length_overflowed= false;
@@ -631,6 +639,7 @@ public:
{
m_length= 0;
m_dec= dec;
m_collation_type= 0;
m_has_explicit_length= false;
m_has_explicit_dec= true;
m_length_overflowed= false;
@@ -640,6 +649,7 @@ public:
{
m_length= length;
m_dec= dec;
m_collation_type= 0;
m_has_explicit_length= true;
m_has_explicit_dec= true;
m_length_overflowed= false;
@@ -677,30 +687,59 @@ struct Lex_field_type_st: public Lex_length_and_dec_st
{
private:
const Type_handler *m_handler;
CHARSET_INFO *m_ci;
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_ci= cs;
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,
const Lex_length_and_dec_st &length,
uint32 flags);
void set_handler_length(const Type_handler *handler, uint32 length)
{
m_handler= handler;
m_ci= NULL;
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)
{
m_handler= 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:
int m_type; // enum_dynamic_column_type is not visible here, so use int
CHARSET_INFO *m_ci;
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_ci= cs;
Lex_length_and_dec_st::operator=(length_and_dec);
}
void set(int type)
{
m_type= type;
m_ci= NULL;
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; }
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_collation_binary_handler
};
struct charset_info_st my_collation_contextually_typed_binary= {0};
struct charset_info_st my_collation_contextually_typed_default= {0};