Main patch MDEV-27896 Wrong result upon COLLATE latin1_bin CHARACTER SET latin1
on the table or the database level
Also fixes MDEV-27782 Wrong columns when using table level `CHARACTER SET utf8mb4 COLLATE DEFAULT` MDEV-28644 Unexpected error on ALTER TABLE t1 CONVERT TO CHARACTER SET utf8mb3, DEFAULT CHARACTER SET utf8mb4
This commit is contained in:
parent
89adedcb9f
commit
208addf484
1960
mysql-test/main/ctype_collate_context.result
Normal file
1960
mysql-test/main/ctype_collate_context.result
Normal file
File diff suppressed because it is too large
Load Diff
366
mysql-test/main/ctype_collate_context.test
Normal file
366
mysql-test/main/ctype_collate_context.test
Normal file
@ -0,0 +1,366 @@
|
||||
--source include/have_utf8mb4.inc
|
||||
|
||||
|
||||
CREATE TABLE t0 (a VARCHAR(64));
|
||||
INSERT INTO t0 VALUES
|
||||
('CHARACTER SET DEFAULT'),
|
||||
('CHARACTER SET latin1'),
|
||||
('CHARACTER SET utf8mb4'),
|
||||
('COLLATE DEFAULT'),
|
||||
('COLLATE utf8mb4_bin'),
|
||||
('COLLATE latin1_swedish_ci'),
|
||||
('COLLATE latin1_bin');
|
||||
|
||||
CREATE TABLE clauses
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
cl1 VARCHAR(64) NOT NULL,
|
||||
cl2 VARCHAR(64) NOT NULL,
|
||||
cl3 VARCHAR(64) NOT NULL,
|
||||
clause_count INT GENERATED ALWAYS AS ((cl1<>'') + (cl2<>'') + (cl3<>'')),
|
||||
clauses TEXT GENERATED ALWAYS AS (CONCAT(cl1,
|
||||
IF(cl2='','',' '), cl2,
|
||||
IF(cl3='','',' '), cl3))
|
||||
);
|
||||
|
||||
# No clauses
|
||||
INSERT INTO clauses (cl1, cl2, cl3)
|
||||
SELECT '' AS cl1, '' AS cl2, '' AS cl3;
|
||||
|
||||
# One clause
|
||||
INSERT INTO clauses (cl1, cl2, cl3)
|
||||
SELECT t0.a AS cl1, '' AS cl2, '' AS cl3
|
||||
FROM t0;
|
||||
|
||||
# Two clauses
|
||||
INSERT INTO clauses (cl1, cl2, cl3)
|
||||
SELECT t0.a AS cl1, t2.a AS cl2, '' AS cl3
|
||||
FROM t0 t0, t0 t2;
|
||||
|
||||
# Three clauses
|
||||
INSERT INTO clauses (cl1, cl2, cl3)
|
||||
SELECT t0.a AS cl1, t2.a AS cl2, t3.a AS cl3
|
||||
FROM t0 t0, t0 t2, t0 t3;
|
||||
|
||||
DROP TABLE t0;
|
||||
|
||||
|
||||
CREATE TABLE results_template
|
||||
(
|
||||
id INT NOT NULL PRIMARY KEY,
|
||||
result TEXT NOT NULL
|
||||
);
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE diff_result_tables_stat(table1 VARCHAR(64),
|
||||
table2 VARCHAR(64),
|
||||
cond VARCHAR(128))
|
||||
BEGIN
|
||||
DECLARE query_counts TEXT DEFAULT
|
||||
'SELECT '
|
||||
' COUNT(*),'
|
||||
' SUM(t1.result=t2.result),'
|
||||
' SUM(t1.result<>t2.result) '
|
||||
'FROM table1 t1 JOIN table2 t2 USING (id)/*$(WHERE)*/';
|
||||
|
||||
SET query_counts=REPLACE(query_counts, 'table1', table1);
|
||||
SET query_counts=REPLACE(query_counts, 'table2', table2);
|
||||
IF (cond<>'')
|
||||
THEN
|
||||
SET query_counts=REPLACE(query_counts, '/*$(WHERE)*/', CONCAT('WHERE ',cond));
|
||||
END IF;
|
||||
EXECUTE IMMEDIATE query_counts;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE diff_result_tables_records(table1 VARCHAR(64),
|
||||
table2 VARCHAR(64),
|
||||
cond VARCHAR(128))
|
||||
BEGIN
|
||||
DECLARE query_records TEXT DEFAULT
|
||||
'SELECT '
|
||||
' '''' AS ``,'
|
||||
' clauses.clauses AS attrs,'
|
||||
' t1.result AS `aaa`,'
|
||||
' t2.result AS `bbb` '
|
||||
' FROM table1 t1'
|
||||
' JOIN table2 t2 USING (id)'
|
||||
' JOIN clauses USING (id) '
|
||||
' WHERE t1.result<>t2.result /*$(COND)*/ ORDER BY t1.id';
|
||||
|
||||
SET query_records=REPLACE(query_records, 'table1', table1);
|
||||
SET query_records=REPLACE(query_records, 'table2', table2);
|
||||
IF (cond<>'')
|
||||
THEN
|
||||
SET query_records=REPLACE(query_records, '/*$(COND)*/', CONCAT('AND ',cond));
|
||||
END IF;
|
||||
EXECUTE IMMEDIATE query_records;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE diff_result_tables(table1 VARCHAR(64),
|
||||
table2 VARCHAR(64),
|
||||
cond VARCHAR(128))
|
||||
BEGIN
|
||||
CALL diff_result_tables_stat(table1, table2, cond);
|
||||
CALL diff_result_tables_records(table1, table2, cond);
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE exec(query_bootstrap TEXT,
|
||||
query_pattern TEXT,
|
||||
query_cleanup TEXT,
|
||||
id INT,
|
||||
clauses TEXT)
|
||||
BEGIN
|
||||
DECLARE query TEXT DEFAULT REPLACE(query_pattern, '/*CSCL*/',clauses);
|
||||
DECLARE result TEXT DEFAULT NULL;
|
||||
DECLARE CONTINUE HANDLER FOR
|
||||
1064, /*ER_PARSE_ERROR*/
|
||||
1302, /*ER_CONFLICTING_DECLARATIONS*/
|
||||
1253 /*ER_COLLATION_CHARSET_MISMATCH*/
|
||||
BEGIN
|
||||
GET DIAGNOSTICS CONDITION 1 result=MESSAGE_TEXT;
|
||||
SET result=CONCAT('ERROR: ', result);
|
||||
END;
|
||||
IF query_bootstrap<>''
|
||||
THEN
|
||||
EXECUTE IMMEDIATE query_bootstrap;
|
||||
END IF;
|
||||
EXECUTE IMMEDIATE query;
|
||||
IF result IS NULL
|
||||
THEN
|
||||
IF query_pattern LIKE '%DATABASE%'
|
||||
THEN
|
||||
SET result=(SELECT CONCAT('CHARACTER SET ', DEFAULT_CHARACTER_SET_NAME,
|
||||
' COLLATE ', DEFAULT_COLLATION_NAME)
|
||||
FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='db1');
|
||||
ELSE
|
||||
SET result=(SELECT CONCAT('CHARACTER SET ', SUBSTRING_INDEX(TABLE_COLLATION,'_',1),
|
||||
' COLLATE ', TABLE_COLLATION)
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test1');
|
||||
END IF;
|
||||
END IF;
|
||||
INSERT INTO results (id, result) VALUES (id, result);
|
||||
IF query_cleanup<>''
|
||||
THEN
|
||||
EXECUTE IMMEDIATE query_cleanup;
|
||||
END IF;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE show_results(query TEXT, clause_count_arg INT)
|
||||
BEGIN
|
||||
SELECT '' AS ``, CONCAT(clause_count_arg, ' clauses') AS `TEST:`;
|
||||
SELECT '' AS ``, COUNT(*) AS `TOTAL`
|
||||
FROM results JOIN clauses USING (id)
|
||||
WHERE clauses.clause_count=clause_count_arg;
|
||||
|
||||
-- Display erroneous results
|
||||
SELECT '' AS ``, COUNT(*) AS `ERROR`
|
||||
FROM results JOIN clauses USING (id)
|
||||
WHERE clauses.clause_count=clause_count_arg
|
||||
AND result RLIKE '^ERROR';
|
||||
|
||||
SELECT '' AS ``, query, clauses AS attrs, result
|
||||
FROM results JOIN clauses USING (id)
|
||||
WHERE clauses.clause_count=clause_count_arg
|
||||
AND result RLIKE '^ERROR' ORDER BY id;
|
||||
|
||||
-- Display successfull results
|
||||
SELECT '' AS ``, COUNT(*) AS `OK`
|
||||
FROM results JOIN clauses USING (id)
|
||||
WHERE clauses.clause_count=clause_count_arg
|
||||
AND result NOT RLIKE '^ERROR';
|
||||
|
||||
SELECT '' AS ``, query, clauses AS attrs, result
|
||||
FROM results JOIN clauses USING (id)
|
||||
WHERE clauses.clause_count=clause_count_arg
|
||||
AND result NOT RLIKE '^ERROR' ORDER BY id;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE run(query_bootstrap TEXT,
|
||||
query TEXT,
|
||||
query_cleanup TEXT,
|
||||
clause_count_arg INT)
|
||||
BEGIN
|
||||
FOR rec IN (SELECT * FROM clauses WHERE clause_count=clause_count_arg)
|
||||
DO
|
||||
CALL exec(query_bootstrap, query, query_cleanup, rec.id, rec.clauses);
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE run_all(query_bootstrap TEXT, query TEXT, query_cleanup TEXT)
|
||||
BEGIN
|
||||
DECLARE msg TEXT;
|
||||
DECLARE count_results INT;
|
||||
DECLARE count_clauses INT;
|
||||
FOR i IN 0..3
|
||||
DO
|
||||
CALL run(query_bootstrap, query, query_cleanup, i);
|
||||
END FOR;
|
||||
SET count_clauses=(SELECT COUNT(*) FROM clauses);
|
||||
SET count_results=(SELECT COUNT(*) FROM results);
|
||||
IF (count_results<>count_clauses)
|
||||
THEN
|
||||
SET msg=CONCAT('Got ', count_results,' rows in `results`; ',
|
||||
'Expected ', count_clauses, ' rows');
|
||||
SIGNAL SQLSTATE '45000'
|
||||
SET MYSQL_ERRNO=30001,
|
||||
MESSAGE_TEXT=msg;
|
||||
END IF;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE show_results_all(query TEXT)
|
||||
BEGIN
|
||||
FOR i IN 0..3
|
||||
DO
|
||||
CALL show_results(query, i);
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
--vertical_results
|
||||
|
||||
--echo #
|
||||
--echo # Running CREATE DATABASE tests
|
||||
--echo # Displaying all results
|
||||
--echo #
|
||||
|
||||
SET @@collation_server=utf8mb4_unicode_ci;
|
||||
CREATE TABLE results LIKE results_template;
|
||||
CALL run_all('','CREATE DATABASE db1 /*CSCL*/', 'DROP DATABASE IF EXISTS db1');
|
||||
CALL show_results_all('CREATE DATABASE');
|
||||
ALTER TABLE results RENAME TO results_create_db;
|
||||
|
||||
--echo #
|
||||
--echo # Running ALTER DATABASE tests
|
||||
--echo #
|
||||
|
||||
CREATE TABLE results LIKE results_template;
|
||||
CALL run_all('CREATE DATABASE db1 CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci',
|
||||
'ALTER DATABASE db1 COMMENT '''' /*CSCL*/',
|
||||
'DROP DATABASE db1');
|
||||
ALTER TABLE results RENAME TO results_alter_db;
|
||||
|
||||
--echo # Displaying results that differ in CREATE DATABASE and ALTER DATABASE
|
||||
--echo # Only queries with no clauses or with COLLATE DEFAULT alone
|
||||
--echo # (without any other COLLATE or CHARACTER SET clauses)
|
||||
--echo # should differ:
|
||||
--echo # CREATE DATABASE db1 COMMENT '' [COLLATE DEFAULT]; -- means @@collation_server
|
||||
--echo # ALTER DATABASE db1 COMMENT '' COLLATE DEFAULT; -- means "the default collation of the current character set of db1"
|
||||
--echo # ALTER DATABASE db1 COMMENT ''; -- means "keep the current db1 collation"
|
||||
|
||||
CALL diff_result_tables('results_create_db', 'results_alter_db', '');
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Running CREATE TABLE tests
|
||||
--echo #
|
||||
|
||||
CREATE DATABASE test1 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE results LIKE results_template;
|
||||
CALL run_all('',
|
||||
'CREATE TABLE test1.t1 (a int) /*CSCL*/',
|
||||
'DROP TABLE IF EXISTS test1.t1');
|
||||
ALTER TABLE results RENAME TO results_create_table;
|
||||
--echo # Expect no difference to CREATE DATABASE
|
||||
CALL diff_result_tables('results_create_db', 'results_create_table', '');
|
||||
|
||||
DROP DATABASE test1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Running ALTER TABLE tests
|
||||
--echo #
|
||||
|
||||
CREATE DATABASE test1 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE results LIKE results_template;
|
||||
CALL run_all('CREATE TABLE test1.t1(a INT) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci',
|
||||
'ALTER TABLE test1.t1 COMMENT '''' /*CSCL*/',
|
||||
'DROP TABLE test1.t1');
|
||||
ALTER TABLE results RENAME TO results_alter_table;
|
||||
--echo # Only queries with no clauses or with COLLATE DEFAULT alone
|
||||
--echo # (without any other COLLATE or CHARACTER SET clauses)
|
||||
--echo # should differ:
|
||||
--echo # CREATE TABLE test1.t1 COMMENT '' [COLLATE DEFAULT]; -- means "the default collation of the database test1"
|
||||
--echo # ALTER TABLE test1.t1 COMMENT '' COLLATE DEFAULT; -- means "the default collation of the current character set of test1.t1"
|
||||
--echo # ALTER TABLE test1.t1 COMMENT ''; -- means "keep the current collation of test.t1"
|
||||
CALL diff_result_tables('results_create_table', 'results_alter_table', '');
|
||||
#SELECT result FROM (
|
||||
#(SELECT * FROM results_create_table)
|
||||
#EXCEPT
|
||||
#(SELECT * FROM results_alter_table)) t1;
|
||||
|
||||
DROP DATABASE test1;
|
||||
|
||||
--echo #
|
||||
--echo # Running ALTER TABLE CONVERT TO tests
|
||||
--echo #
|
||||
|
||||
CREATE DATABASE test1 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE results LIKE results_template;
|
||||
CALL run_all('CREATE TABLE test1.t1(a INT) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci',
|
||||
'ALTER TABLE test1.t1 CONVERT TO /*CSCL*/',
|
||||
'DROP TABLE test1.t1');
|
||||
ALTER TABLE results RENAME TO results_convert_table;
|
||||
|
||||
--echo # CONVERT TO COLLATE (without CHARACTER SET) is not supported yet
|
||||
|
||||
CALL diff_result_tables_stat('results_alter_table', 'results_convert_table','');
|
||||
|
||||
--echo # Everything that did not fail on syntax error
|
||||
--echo # should give equal results with ALTER TABLE DEFAULT CHARACTER SET
|
||||
--echo # Expect 0 non-equal results:
|
||||
CALL diff_result_tables('results_alter_table', 'results_convert_table',
|
||||
't2.result NOT RLIKE ''SQL syntax''');
|
||||
|
||||
DROP DATABASE test1;
|
||||
|
||||
--horizontal_results
|
||||
|
||||
|
||||
DROP PROCEDURE show_results_all;
|
||||
DROP PROCEDURE run_all;
|
||||
DROP PROCEDURE show_results;
|
||||
DROP PROCEDURE exec;
|
||||
DROP PROCEDURE run;
|
||||
DROP PROCEDURE diff_result_tables;
|
||||
DROP PROCEDURE diff_result_tables_stat;
|
||||
DROP PROCEDURE diff_result_tables_records;
|
||||
DROP TABLE clauses;
|
||||
DROP TABLE results_template;
|
||||
DROP TABLE results_create_db;
|
||||
DROP TABLE results_alter_db;
|
||||
DROP TABLE results_create_table;
|
||||
DROP TABLE results_alter_table;
|
||||
DROP TABLE results_convert_table;
|
106
mysql-test/main/ctype_collate_database.result
Normal file
106
mysql-test/main/ctype_collate_database.result
Normal file
@ -0,0 +1,106 @@
|
||||
#
|
||||
# MDEV-27896 Wrong result upon COLLATE latin1_bin CHARACTER SET latin1 on the table or the database level
|
||||
#
|
||||
CREATE DATABASE db1 COLLATE latin1_bin CHARACTER SET latin1;
|
||||
SHOW CREATE DATABASE db1;
|
||||
Database Create Database
|
||||
db1 CREATE DATABASE `db1` /*!40100 DEFAULT CHARACTER SET latin1 COLLATE latin1_bin */
|
||||
DROP DATABASE db1;
|
||||
CREATE VIEW cscl AS
|
||||
SELECT
|
||||
DEFAULT_CHARACTER_SET_NAME,
|
||||
DEFAULT_COLLATION_NAME
|
||||
FROM
|
||||
INFORMATION_SCHEMA.SCHEMATA
|
||||
WHERE
|
||||
SCHEMA_NAME='db1';
|
||||
SET collation_server=utf8mb4_unicode_ci;
|
||||
CREATE DATABASE db1 COMMENT 'test';
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
utf8mb4 utf8mb4_unicode_ci
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1 COLLATE DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
utf8mb4 utf8mb4_general_ci
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1 COLLATE latin1_bin;
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
latin1 latin1_bin
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1 CHARACTER SET latin1;
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
latin1 latin1_swedish_ci
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1 CHARACTER SET latin1 COLLATE DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
latin1 latin1_swedish_ci
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1 CHARACTER SET latin1 COLLATE latin1_bin;
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
latin1 latin1_bin
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1 COLLATE DEFAULT CHARACTER SET latin1;
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
latin1 latin1_swedish_ci
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1 COLLATE latin1_bin CHARACTER SET latin1;
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
latin1 latin1_bin
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1 CHARACTER SET DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
utf8mb4 utf8mb4_general_ci
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1 CHARACTER SET DEFAULT CHARACTER SET DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
utf8mb4 utf8mb4_general_ci
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1 CHARACTER SET DEFAULT COLLATE DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
utf8mb4 utf8mb4_general_ci
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1 COLLATE DEFAULT CHARACTER SET DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
utf8mb4 utf8mb4_general_ci
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1 CHARACTER SET DEFAULT CHARACTER SET utf8mb4;
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
utf8mb4 utf8mb4_general_ci
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1 CHARACTER SET utf8mb4 CHARACTER SET DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
utf8mb4 utf8mb4_general_ci
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1 CHARACTER SET DEFAULT CHARACTER SET latin1;
|
||||
ERROR HY000: Conflicting declarations: 'CHARACTER SET DEFAULT (utf8mb4)' and 'CHARACTER SET latin1'
|
||||
CREATE DATABASE db1 CHARACTER SET latin1 CHARACTER SET DEFAULT;
|
||||
ERROR HY000: Conflicting declarations: 'CHARACTER SET latin1' and 'CHARACTER SET DEFAULT (utf8mb4)'
|
||||
CREATE DATABASE db1 CHARACTER SET DEFAULT COLLATE latin1_bin;
|
||||
ERROR 42000: COLLATION 'latin1_bin' is not valid for CHARACTER SET 'utf8mb4'
|
||||
CREATE DATABASE db1 COLLATE latin1_bin CHARACTER SET DEFAULT;
|
||||
ERROR 42000: COLLATION 'latin1_bin' is not valid for CHARACTER SET 'utf8mb4'
|
||||
CREATE DATABASE db1 CHARACTER SET DEFAULT COLLATE utf8mb4_bin;
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
utf8mb4 utf8mb4_bin
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1 COLLATE utf8mb4_bin CHARACTER SET DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME
|
||||
utf8mb4 utf8mb4_bin
|
||||
DROP DATABASE db1;
|
||||
DROP VIEW cscl;
|
96
mysql-test/main/ctype_collate_database.test
Normal file
96
mysql-test/main/ctype_collate_database.test
Normal file
@ -0,0 +1,96 @@
|
||||
--source include/have_utf8mb4.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-27896 Wrong result upon COLLATE latin1_bin CHARACTER SET latin1 on the table or the database level
|
||||
--echo #
|
||||
|
||||
CREATE DATABASE db1 COLLATE latin1_bin CHARACTER SET latin1;
|
||||
SHOW CREATE DATABASE db1;
|
||||
DROP DATABASE db1;
|
||||
|
||||
|
||||
CREATE VIEW cscl AS
|
||||
SELECT
|
||||
DEFAULT_CHARACTER_SET_NAME,
|
||||
DEFAULT_COLLATION_NAME
|
||||
FROM
|
||||
INFORMATION_SCHEMA.SCHEMATA
|
||||
WHERE
|
||||
SCHEMA_NAME='db1';
|
||||
|
||||
SET collation_server=utf8mb4_unicode_ci;
|
||||
CREATE DATABASE db1 COMMENT 'test';
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
CREATE DATABASE db1 COLLATE DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
CREATE DATABASE db1 COLLATE latin1_bin;
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
CREATE DATABASE db1 CHARACTER SET latin1;
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
CREATE DATABASE db1 CHARACTER SET latin1 COLLATE DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
CREATE DATABASE db1 CHARACTER SET latin1 COLLATE latin1_bin;
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
CREATE DATABASE db1 COLLATE DEFAULT CHARACTER SET latin1;
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
CREATE DATABASE db1 COLLATE latin1_bin CHARACTER SET latin1;
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
CREATE DATABASE db1 CHARACTER SET DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
CREATE DATABASE db1 CHARACTER SET DEFAULT CHARACTER SET DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
CREATE DATABASE db1 CHARACTER SET DEFAULT COLLATE DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
CREATE DATABASE db1 COLLATE DEFAULT CHARACTER SET DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
CREATE DATABASE db1 CHARACTER SET DEFAULT CHARACTER SET utf8mb4;
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
CREATE DATABASE db1 CHARACTER SET utf8mb4 CHARACTER SET DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
--error ER_CONFLICTING_DECLARATIONS
|
||||
CREATE DATABASE db1 CHARACTER SET DEFAULT CHARACTER SET latin1;
|
||||
--error ER_CONFLICTING_DECLARATIONS
|
||||
CREATE DATABASE db1 CHARACTER SET latin1 CHARACTER SET DEFAULT;
|
||||
|
||||
--error ER_COLLATION_CHARSET_MISMATCH
|
||||
CREATE DATABASE db1 CHARACTER SET DEFAULT COLLATE latin1_bin;
|
||||
--error ER_COLLATION_CHARSET_MISMATCH
|
||||
CREATE DATABASE db1 COLLATE latin1_bin CHARACTER SET DEFAULT;
|
||||
|
||||
CREATE DATABASE db1 CHARACTER SET DEFAULT COLLATE utf8mb4_bin;
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
CREATE DATABASE db1 COLLATE utf8mb4_bin CHARACTER SET DEFAULT;
|
||||
SELECT * FROM cscl;
|
||||
DROP DATABASE db1;
|
||||
|
||||
DROP VIEW cscl;
|
27
mysql-test/main/ctype_collate_table.result
Normal file
27
mysql-test/main/ctype_collate_table.result
Normal file
@ -0,0 +1,27 @@
|
||||
#
|
||||
# MDEV-27896 Wrong result upon `COLLATE latin1_bin CHARACTER SET latin1` on the table or the database level
|
||||
#
|
||||
CREATE TABLE t1 (a CHAR) COLLATE latin1_bin CHARACTER SET latin1;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` char(1) COLLATE latin1_bin DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_bin
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-27782 Wrong columns when using table level `CHARACTER SET utf8mb4 COLLATE DEFAULT`
|
||||
#
|
||||
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;
|
||||
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) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4
|
||||
DROP TABLE t1;
|
22
mysql-test/main/ctype_collate_table.test
Normal file
22
mysql-test/main/ctype_collate_table.test
Normal file
@ -0,0 +1,22 @@
|
||||
--source include/have_utf8mb4.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-27896 Wrong result upon `COLLATE latin1_bin CHARACTER SET latin1` on the table or the database level
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a CHAR) COLLATE latin1_bin CHARACTER SET latin1;
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-27782 Wrong columns when using table level `CHARACTER SET utf8mb4 COLLATE DEFAULT`
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a CHAR(10)) CHARACTER SET latin1 COLLATE DEFAULT;
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a CHAR(10)) CHARACTER SET utf8mb4 COLLATE DEFAULT;
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
@ -78,37 +78,113 @@ ALTER DATABASE `` DEFAULT CHARACTER SET latin2;
|
||||
ERROR 42000: Incorrect database name ''
|
||||
USE test;
|
||||
#
|
||||
# Start of 10.0 tests
|
||||
# End of 10.0 tests
|
||||
#
|
||||
#
|
||||
# Start of 10.9 tests
|
||||
#
|
||||
#
|
||||
# MDEV-7387 Alter table xxx CHARACTER SET utf8, CONVERT TO CHARACTER SET latin1 should fail
|
||||
# MDEV-28644 Unexpected error on ALTER TABLE t1 CONVERT TO CHARACTER SET utf8mb3, DEFAULT CHARACTER SET utf8mb4
|
||||
#
|
||||
CREATE DATABASE tmp DEFAULT CHARACTER SET latin5;
|
||||
USE tmp;
|
||||
CREATE TABLE t1 (a VARCHAR(10)) CHARACTER SET DEFAULT, CHARACTER SET utf8;
|
||||
ERROR HY000: Conflicting declarations: 'CHARACTER SET DEFAULT' and 'CHARACTER SET utf8mb3'
|
||||
ERROR HY000: Conflicting declarations: 'CHARACTER SET DEFAULT (latin5)' and 'CHARACTER SET utf8mb3'
|
||||
CREATE TABLE t1 (a VARCHAR(10)) CHARACTER SET utf8, CHARACTER SET DEFAULT;
|
||||
ERROR HY000: Conflicting declarations: 'CHARACTER SET utf8mb3' and 'CHARACTER SET DEFAULT'
|
||||
ERROR HY000: Conflicting declarations: 'CHARACTER SET utf8mb3' and 'CHARACTER SET DEFAULT (latin5)'
|
||||
CREATE TABLE t1 (a VARCHAR(10)) CHARACTER SET utf8, CHARACTER SET utf8;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a VARCHAR(10)) CHARACTER SET DEFAULT, CHARACTER SET DEFAULT;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1, b VARCHAR(10) CHARACTER SET utf8);
|
||||
ALTER TABLE t1 CONVERT TO CHARACTER SET utf8, CHARACTER SET latin1;
|
||||
ERROR HY000: Conflicting declarations: 'CHARACTER SET utf8mb3' and 'CHARACTER SET latin1'
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` varchar(10) CHARACTER SET utf8mb3 DEFAULT NULL,
|
||||
`b` varchar(10) CHARACTER SET utf8mb3 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
ALTER TABLE t1 CONVERT TO CHARACTER SET utf8, CHARACTER SET DEFAULT;
|
||||
ERROR HY000: Conflicting declarations: 'CHARACTER SET utf8mb3' and 'CHARACTER SET DEFAULT'
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` varchar(10) CHARACTER SET utf8mb3 DEFAULT NULL,
|
||||
`b` varchar(10) CHARACTER SET utf8mb3 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin5
|
||||
ALTER TABLE t1 CONVERT TO CHARACTER SET latin1, CHARACTER SET utf8;
|
||||
ERROR HY000: Conflicting declarations: 'CHARACTER SET latin1' and 'CHARACTER SET utf8mb3'
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` varchar(10) CHARACTER SET latin1 DEFAULT NULL,
|
||||
`b` varchar(10) CHARACTER SET latin1 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3
|
||||
ALTER TABLE t1 CONVERT TO CHARACTER SET latin1, CHARACTER SET DEFAULT;
|
||||
ERROR HY000: Conflicting declarations: 'CHARACTER SET latin1' and 'CHARACTER SET DEFAULT'
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` varchar(10) CHARACTER SET latin1 DEFAULT NULL,
|
||||
`b` varchar(10) CHARACTER SET latin1 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin5
|
||||
ALTER TABLE t1 CONVERT TO CHARACTER SET DEFAULT, CHARACTER SET utf8;
|
||||
ERROR HY000: Conflicting declarations: 'CHARACTER SET latin5' and 'CHARACTER SET utf8mb3'
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` varchar(10) CHARACTER SET latin5 DEFAULT NULL,
|
||||
`b` varchar(10) CHARACTER SET latin5 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3
|
||||
ALTER TABLE t1 CONVERT TO CHARACTER SET DEFAULT, CHARACTER SET latin1;
|
||||
ERROR HY000: Conflicting declarations: 'CHARACTER SET latin5' and 'CHARACTER SET latin1'
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` varchar(10) CHARACTER SET latin5 DEFAULT NULL,
|
||||
`b` varchar(10) CHARACTER SET latin5 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
ALTER TABLE t1 CHARACTER SET latin1, CONVERT TO CHARACTER SET utf8;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` varchar(10) CHARACTER SET utf8mb3 DEFAULT NULL,
|
||||
`b` varchar(10) CHARACTER SET utf8mb3 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
ALTER TABLE t1 CHARACTER SET DEFAULT, CONVERT TO CHARACTER SET utf8;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` varchar(10) CHARACTER SET utf8mb3 DEFAULT NULL,
|
||||
`b` varchar(10) CHARACTER SET utf8mb3 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin5
|
||||
ALTER TABLE t1 CHARACTER SET utf8, CONVERT TO CHARACTER SET latin1;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` varchar(10) CHARACTER SET latin1 DEFAULT NULL,
|
||||
`b` varchar(10) CHARACTER SET latin1 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3
|
||||
ALTER TABLE t1 CHARACTER SET DEFAULT, CONVERT TO CHARACTER SET latin1;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` varchar(10) CHARACTER SET latin1 DEFAULT NULL,
|
||||
`b` varchar(10) CHARACTER SET latin1 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin5
|
||||
ALTER TABLE t1 CHARACTER SET utf8, CONVERT TO CHARACTER SET DEFAULT;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` varchar(10) CHARACTER SET latin5 DEFAULT NULL,
|
||||
`b` varchar(10) CHARACTER SET latin5 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3
|
||||
ALTER TABLE t1 CHARACTER SET latin1, CONVERT TO CHARACTER SET DEFAULT;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` varchar(10) CHARACTER SET latin5 DEFAULT NULL,
|
||||
`b` varchar(10) CHARACTER SET latin5 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1;
|
||||
DROP DATABASE tmp;
|
||||
USE test;
|
||||
#
|
||||
# End of 10.0 tests
|
||||
# End of 10.9 tests
|
||||
#
|
||||
|
@ -108,11 +108,16 @@ ALTER DATABASE `` DEFAULT CHARACTER SET latin2;
|
||||
USE test;
|
||||
|
||||
--echo #
|
||||
--echo # Start of 10.0 tests
|
||||
--echo # End of 10.0 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # Start of 10.9 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-7387 Alter table xxx CHARACTER SET utf8, CONVERT TO CHARACTER SET latin1 should fail
|
||||
--echo # MDEV-28644 Unexpected error on ALTER TABLE t1 CONVERT TO CHARACTER SET utf8mb3, DEFAULT CHARACTER SET utf8mb4
|
||||
--echo #
|
||||
CREATE DATABASE tmp DEFAULT CHARACTER SET latin5;
|
||||
USE tmp;
|
||||
@ -125,23 +130,48 @@ DROP TABLE t1;
|
||||
CREATE TABLE t1 (a VARCHAR(10)) CHARACTER SET DEFAULT, CHARACTER SET DEFAULT;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1, b VARCHAR(10) CHARACTER SET utf8);
|
||||
--error ER_CONFLICTING_DECLARATIONS
|
||||
ALTER TABLE t1 CONVERT TO CHARACTER SET utf8, CHARACTER SET latin1;
|
||||
--error ER_CONFLICTING_DECLARATIONS
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
ALTER TABLE t1 CONVERT TO CHARACTER SET utf8, CHARACTER SET DEFAULT;
|
||||
--error ER_CONFLICTING_DECLARATIONS
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
ALTER TABLE t1 CONVERT TO CHARACTER SET latin1, CHARACTER SET utf8;
|
||||
--error ER_CONFLICTING_DECLARATIONS
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
ALTER TABLE t1 CONVERT TO CHARACTER SET latin1, CHARACTER SET DEFAULT;
|
||||
--error ER_CONFLICTING_DECLARATIONS
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
ALTER TABLE t1 CONVERT TO CHARACTER SET DEFAULT, CHARACTER SET utf8;
|
||||
--error ER_CONFLICTING_DECLARATIONS
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
ALTER TABLE t1 CONVERT TO CHARACTER SET DEFAULT, CHARACTER SET latin1;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
ALTER TABLE t1 CHARACTER SET latin1, CONVERT TO CHARACTER SET utf8;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
ALTER TABLE t1 CHARACTER SET DEFAULT, CONVERT TO CHARACTER SET utf8;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
ALTER TABLE t1 CHARACTER SET utf8, CONVERT TO CHARACTER SET latin1;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
ALTER TABLE t1 CHARACTER SET DEFAULT, CONVERT TO CHARACTER SET latin1;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
ALTER TABLE t1 CHARACTER SET utf8, CONVERT TO CHARACTER SET DEFAULT;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
ALTER TABLE t1 CHARACTER SET latin1, CONVERT TO CHARACTER SET DEFAULT;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP DATABASE tmp;
|
||||
USE test;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.0 tests
|
||||
--echo # End of 10.9 tests
|
||||
--echo #
|
||||
|
@ -7921,24 +7921,6 @@ int ha_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal)
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
|
||||
bool HA_CREATE_INFO::check_conflicting_charset_declarations(CHARSET_INFO *cs)
|
||||
{
|
||||
if ((used_fields & HA_CREATE_USED_DEFAULT_CHARSET) &&
|
||||
/* DEFAULT vs explicit, or explicit vs DEFAULT */
|
||||
(((default_table_charset == NULL) != (cs == NULL)) ||
|
||||
/* Two different explicit character sets */
|
||||
(default_table_charset && cs &&
|
||||
!my_charset_same(default_table_charset, cs))))
|
||||
{
|
||||
my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
|
||||
"CHARACTER SET ", default_table_charset ?
|
||||
default_table_charset->cs_name.str : "DEFAULT",
|
||||
"CHARACTER SET ", cs ? cs->cs_name.str : "DEFAULT");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Remove all indexes for a given table from global index statistics */
|
||||
|
||||
static
|
||||
|
@ -2289,33 +2289,6 @@ struct HA_CREATE_INFO: public Table_scope_and_contents_source_st,
|
||||
Schema_specification_st::init();
|
||||
alter_info= NULL;
|
||||
}
|
||||
bool check_conflicting_charset_declarations(CHARSET_INFO *cs);
|
||||
bool add_table_option_default_charset(CHARSET_INFO *cs)
|
||||
{
|
||||
// cs can be NULL, e.g.: CREATE TABLE t1 (..) CHARACTER SET DEFAULT;
|
||||
if (check_conflicting_charset_declarations(cs))
|
||||
return true;
|
||||
default_table_charset= cs;
|
||||
used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
|
||||
return false;
|
||||
}
|
||||
bool add_alter_list_item_convert_to_charset(CHARSET_INFO *cs)
|
||||
{
|
||||
/*
|
||||
cs cannot be NULL, as sql_yacc.yy translates
|
||||
CONVERT TO CHARACTER SET DEFAULT
|
||||
to
|
||||
CONVERT TO CHARACTER SET <character-set-of-the-current-database>
|
||||
TODO: Shouldn't we postpone resolution of DEFAULT until the
|
||||
character set of the table owner database is loaded from its db.opt?
|
||||
*/
|
||||
DBUG_ASSERT(cs);
|
||||
if (check_conflicting_charset_declarations(cs))
|
||||
return true;
|
||||
alter_table_convert_to_charset= default_table_charset= cs;
|
||||
used_fields|= (HA_CREATE_USED_CHARSET | HA_CREATE_USED_DEFAULT_CHARSET);
|
||||
return false;
|
||||
}
|
||||
ulong table_options_with_row_type()
|
||||
{
|
||||
if (row_type == ROW_TYPE_DYNAMIC || row_type == ROW_TYPE_PAGE)
|
||||
@ -2323,6 +2296,10 @@ struct HA_CREATE_INFO: public Table_scope_and_contents_source_st,
|
||||
else
|
||||
return table_options;
|
||||
}
|
||||
bool resolve_to_charset_collation_context(THD *thd,
|
||||
const Lex_table_charset_collation_attrs_st &default_cscl,
|
||||
const Lex_table_charset_collation_attrs_st &convert_cscl,
|
||||
const Charset_collation_context &ctx);
|
||||
};
|
||||
|
||||
|
||||
@ -2333,16 +2310,23 @@ struct HA_CREATE_INFO: public Table_scope_and_contents_source_st,
|
||||
struct Table_specification_st: public HA_CREATE_INFO,
|
||||
public DDL_options_st
|
||||
{
|
||||
Lex_table_charset_collation_attrs_st default_charset_collation;
|
||||
Lex_table_charset_collation_attrs_st convert_charset_collation;
|
||||
|
||||
// Deep initialization
|
||||
void init()
|
||||
{
|
||||
HA_CREATE_INFO::init();
|
||||
DDL_options_st::init();
|
||||
default_charset_collation.init();
|
||||
convert_charset_collation.init();
|
||||
}
|
||||
void init(DDL_options_st::Options options_arg)
|
||||
{
|
||||
HA_CREATE_INFO::init();
|
||||
DDL_options_st::init(options_arg);
|
||||
default_charset_collation.init();
|
||||
convert_charset_collation.init();
|
||||
}
|
||||
/*
|
||||
Quick initialization, for parser.
|
||||
@ -2354,6 +2338,46 @@ struct Table_specification_st: public HA_CREATE_INFO,
|
||||
{
|
||||
HA_CREATE_INFO::options= 0;
|
||||
DDL_options_st::init();
|
||||
default_charset_collation.init();
|
||||
convert_charset_collation.init();
|
||||
}
|
||||
|
||||
bool add_table_option_convert_charset(CHARSET_INFO *cs)
|
||||
{
|
||||
// cs can be NULL, e.g.: ALTER TABLE t1 CONVERT TO CHARACTER SET DEFAULT;
|
||||
used_fields|= (HA_CREATE_USED_CHARSET | HA_CREATE_USED_DEFAULT_CHARSET);
|
||||
return cs ?
|
||||
convert_charset_collation.merge_exact_charset(Lex_exact_charset(cs)) :
|
||||
convert_charset_collation.merge_charset_default();
|
||||
}
|
||||
bool add_table_option_convert_collation(const Lex_extended_collation_st &cl)
|
||||
{
|
||||
used_fields|= (HA_CREATE_USED_CHARSET | HA_CREATE_USED_DEFAULT_CHARSET);
|
||||
return convert_charset_collation.merge_collation(cl);
|
||||
}
|
||||
|
||||
bool add_table_option_default_charset(CHARSET_INFO *cs)
|
||||
{
|
||||
// cs can be NULL, e.g.: CREATE TABLE t1 (..) CHARACTER SET DEFAULT;
|
||||
used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
|
||||
return cs ?
|
||||
default_charset_collation.merge_exact_charset(Lex_exact_charset(cs)) :
|
||||
default_charset_collation.merge_charset_default();
|
||||
}
|
||||
bool add_table_option_default_collation(const Lex_extended_collation_st &cl)
|
||||
{
|
||||
used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
|
||||
return default_charset_collation.merge_collation(cl);
|
||||
}
|
||||
|
||||
bool resolve_to_charset_collation_context(THD *thd,
|
||||
const Charset_collation_context &ctx)
|
||||
{
|
||||
return HA_CREATE_INFO::
|
||||
resolve_to_charset_collation_context(thd,
|
||||
default_charset_collation,
|
||||
convert_charset_collation,
|
||||
ctx);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -37,6 +37,22 @@ raise_ER_CONFLICTING_DECLARATIONS(const char *clause1,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
raise_ER_CONFLICTING_DECLARATIONS(const char *clause1,
|
||||
const char *name1,
|
||||
const char *name1_part2,
|
||||
const char *clause2,
|
||||
const char *name2,
|
||||
bool reverse_order)
|
||||
{
|
||||
char def[MY_CS_NAME_SIZE * 2];
|
||||
my_snprintf(def, sizeof(def), "%s (%s)", name1, name1_part2);
|
||||
raise_ER_CONFLICTING_DECLARATIONS(clause1, def,
|
||||
clause2, name2,
|
||||
reverse_order);
|
||||
}
|
||||
|
||||
|
||||
bool Lex_exact_charset::raise_if_not_equal(const Lex_exact_charset &rhs) const
|
||||
{
|
||||
if (m_ci == rhs.m_ci)
|
||||
@ -537,3 +553,124 @@ bool Lex_exact_charset_extended_collation_attrs_st::
|
||||
DBUG_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Lex_extended_charset_extended_collation_attrs_st::merge_charset_default()
|
||||
{
|
||||
if (m_charset_order == CHARSET_TYPE_EMPTY)
|
||||
m_charset_order= CHARSET_TYPE_CONTEXT;
|
||||
Lex_opt_context_charset_st::merge_charset_default();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Lex_extended_charset_extended_collation_attrs_st::
|
||||
merge_exact_charset(const Lex_exact_charset &cs)
|
||||
{
|
||||
m_had_charset_exact= true;
|
||||
if (m_charset_order == CHARSET_TYPE_EMPTY)
|
||||
m_charset_order= CHARSET_TYPE_EXACT;
|
||||
return Lex_exact_charset_extended_collation_attrs_st::merge_exact_charset(cs);
|
||||
}
|
||||
|
||||
|
||||
bool Lex_extended_charset_extended_collation_attrs_st::
|
||||
raise_if_charset_conflicts_with_default(
|
||||
const Lex_exact_charset_opt_extended_collate &def) const
|
||||
{
|
||||
DBUG_ASSERT(m_charset_order != CHARSET_TYPE_EMPTY || is_empty());
|
||||
if (!my_charset_same(def.collation().charset_info(), m_ci))
|
||||
{
|
||||
raise_ER_CONFLICTING_DECLARATIONS("CHARACTER SET ", "DEFAULT",
|
||||
def.collation().charset_info()->cs_name.str,
|
||||
"CHARACTER SET ", m_ci->cs_name.str,
|
||||
m_charset_order == CHARSET_TYPE_EXACT);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
CHARSET_INFO *
|
||||
Lex_extended_charset_extended_collation_attrs_st::
|
||||
resolved_to_context(const Charset_collation_context &ctx) const
|
||||
{
|
||||
if (Lex_opt_context_charset_st::is_empty())
|
||||
{
|
||||
// Without CHARACTER SET DEFAULT
|
||||
return Lex_exact_charset_extended_collation_attrs_st::
|
||||
resolved_to_character_set(ctx.collate_default().charset_info());
|
||||
}
|
||||
|
||||
// With CHARACTER SET DEFAULT
|
||||
switch (type()) {
|
||||
case TYPE_EMPTY:
|
||||
// CHARACTER SET DEFAULT;
|
||||
return ctx.charset_default().charset().charset_info();
|
||||
|
||||
case TYPE_CHARACTER_SET:
|
||||
// CHARACTER SET DEFAULT CHARACTER SET cs_exact
|
||||
if (raise_if_charset_conflicts_with_default(ctx.charset_default()))
|
||||
{
|
||||
/*
|
||||
A possible scenario:
|
||||
SET character_set_server=utf8mb4;
|
||||
CREATE DATABASE db1 CHARACTER SET latin1 CHARACTER SET DEFAULT;
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
return m_ci;
|
||||
|
||||
case TYPE_COLLATE_EXACT:
|
||||
{
|
||||
/*
|
||||
CREATE DATABASE db1
|
||||
COLLATE cl_exact
|
||||
[ CHARACTER SET cs_exact ]
|
||||
CHARACTER SET DEFAULT;
|
||||
*/
|
||||
if (m_had_charset_exact &&
|
||||
raise_if_charset_conflicts_with_default(ctx.charset_default()))
|
||||
{
|
||||
/*
|
||||
A possible scenario:
|
||||
SET character_set_server=utf8mb4;
|
||||
CREATE DATABASE db1
|
||||
COLLATE latin1_bin
|
||||
CHARACTER SET latin1
|
||||
CHARACTER SET DEFAULT;
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
Now check that "COLLATE cl_exact" does not conflict with
|
||||
CHARACTER SET DEFAULT.
|
||||
*/
|
||||
if (ctx.charset_default().
|
||||
raise_if_not_applicable(Lex_exact_collation(m_ci)))
|
||||
{
|
||||
/*
|
||||
A possible scenario:
|
||||
SET character_set_server=utf8mb4;
|
||||
CREATE DATABASE db1
|
||||
COLLATE latin1_bin
|
||||
CHARACTER SET DEFAULT;
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
return m_ci;
|
||||
}
|
||||
|
||||
case TYPE_COLLATE_CONTEXTUALLY_TYPED:
|
||||
/*
|
||||
Both CHARACTER SET and COLLATE are contextual:
|
||||
ALTER DATABASE db1 CHARACTER SET DEFAULT COLLATE DEFAULT;
|
||||
ALTER DATABASE db1 COLLATE DEFAULT CHARACTER SET DEFAULT;
|
||||
*/
|
||||
return Lex_exact_charset_extended_collation_attrs_st::
|
||||
resolved_to_character_set(ctx.charset_default().
|
||||
collation().charset_info());
|
||||
}
|
||||
DBUG_ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -37,6 +37,41 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
An optional contextually typed character set:
|
||||
[ CHARACTER SET DEFAULT ]
|
||||
*/
|
||||
class Lex_opt_context_charset_st
|
||||
{
|
||||
/*
|
||||
Currently we support only DEFAULT as a possible value.
|
||||
So "bool" is enough.
|
||||
*/
|
||||
bool m_had_charset_default;
|
||||
public:
|
||||
void init()
|
||||
{
|
||||
m_had_charset_default= false;
|
||||
}
|
||||
void merge_charset_default()
|
||||
{
|
||||
/*
|
||||
Ok to specify CHARACTER SET DEFAULT multiple times.
|
||||
No error raised here.
|
||||
*/
|
||||
m_had_charset_default= true;
|
||||
}
|
||||
bool is_empty() const
|
||||
{
|
||||
return !m_had_charset_default;
|
||||
}
|
||||
bool is_contextually_typed_charset_default() const
|
||||
{
|
||||
return m_had_charset_default;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
A contextually typed collation, e.g.:
|
||||
COLLATE DEFAULT
|
||||
@ -407,6 +442,132 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class Charset_collation_context
|
||||
{
|
||||
/*
|
||||
Although the goal of m_charset_default is to store the meaning
|
||||
of CHARACTER SET DEFAULT, it does not necessarily point to a
|
||||
default collation of CHARACTER SET DEFAULT. It can point to its any
|
||||
arbitrary collation.
|
||||
For performance purposes we don't need to find the default
|
||||
collation at the instantiation time of "this", because:
|
||||
- m_charset_default may not be even needed during the resolution
|
||||
- when it's needed, in many cases it's passed to my_charset_same(),
|
||||
which does not need the default collation again.
|
||||
|
||||
Note, m_charset_default and m_collate_default are not necessarily equal.
|
||||
|
||||
- The default value for CHARACTER SET is taken from the upper level:
|
||||
CREATE DATABASE db1 CHARACTER SET DEFAULT; <-- @@character_set_server
|
||||
ALTER DATABASE db1 CHARACTER SET DEFAULT; <-- @@character_set_server
|
||||
|
||||
- The default value for COLLATE is taken from the upper level for CREATE:
|
||||
CREATE DATABASE db1 COLLATE DEFAULT; <-- @@collation_server
|
||||
CREATE TABLE db1.t1 COLLATE DEFAULT; <-- character set of "db1"
|
||||
|
||||
- The default value for COLLATE is taken from the same level for ALTER:
|
||||
ALTER DATABASE db1 COLLATE DEFAULT; <-- the default collation of the
|
||||
current db1 character set
|
||||
ALTER TABLE db1.t1 COLLATE DEFAULT; <-- the default collation of the
|
||||
current db1.t1 character set
|
||||
*/
|
||||
|
||||
// comes from the upper level
|
||||
Lex_exact_charset_opt_extended_collate m_charset_default;
|
||||
|
||||
// comes from the upper or the current level
|
||||
Lex_exact_collation m_collate_default;
|
||||
public:
|
||||
Charset_collation_context(CHARSET_INFO *charset_default,
|
||||
CHARSET_INFO *collate_default)
|
||||
:m_charset_default(charset_default,
|
||||
!(charset_default->state & MY_CS_PRIMARY)),
|
||||
m_collate_default(collate_default)
|
||||
{ }
|
||||
const Lex_exact_charset_opt_extended_collate charset_default() const
|
||||
{
|
||||
return m_charset_default;
|
||||
}
|
||||
const Lex_exact_collation collate_default() const
|
||||
{
|
||||
return m_collate_default;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
A universal container. It can store at the same time:
|
||||
- CHARACTER SET DEFAULT
|
||||
- CHARACTER SET cs_exact
|
||||
- COLLATE {cl_exact|cl_context}
|
||||
All three parts can co-exist.
|
||||
All three parts are optional.
|
||||
Parts can come in any arbitrary order, e.g:
|
||||
|
||||
CHARACTER SET DEFAULT [CHARACTER SET latin1] COLLATE latin1_bin
|
||||
CHARACTER SET latin1 CHARACTER SET DEFAULT COLLATE latin1_bin
|
||||
COLLATE latin1_bin [CHARACTER SET latin1] CHARACTER SET DEFAULT
|
||||
COLLATE latin1_bin CHARACTER SET DEFAULT [CHARACTER SET latin1]
|
||||
*/
|
||||
class Lex_extended_charset_extended_collation_attrs_st:
|
||||
public Lex_opt_context_charset_st,
|
||||
public Lex_exact_charset_extended_collation_attrs_st
|
||||
{
|
||||
enum charset_type_t
|
||||
{
|
||||
CHARSET_TYPE_EMPTY,
|
||||
CHARSET_TYPE_CONTEXT,
|
||||
CHARSET_TYPE_EXACT
|
||||
};
|
||||
/*
|
||||
Which part came first:
|
||||
- CHARACTER SET DEFAULT or
|
||||
- CHARACTER SET cs_exact
|
||||
e.g. to produce error messages preserving the user typed
|
||||
order of CHARACTER SET clauses in case of conflicts.
|
||||
*/
|
||||
charset_type_t m_charset_order;
|
||||
/*
|
||||
The parent class Lex_exact_charset_extended_collation_attrs_st
|
||||
does not let know if a "COLLATE cl_exact" was used in combination with
|
||||
"CHARACTER SET cs_exact" or just alone.
|
||||
Here we need to distinguish:
|
||||
- CHARACTER SET cs_exact COLLATE cl_exact, or
|
||||
- COLLATE cl_exact CHARACTER SET cs_exact
|
||||
versus just:
|
||||
- COLLATE cl_exact
|
||||
to produce better error messages in case of conflicts.
|
||||
So let's add a flag member:
|
||||
*/
|
||||
bool m_had_charset_exact;
|
||||
public:
|
||||
void init()
|
||||
{
|
||||
Lex_opt_context_charset_st::init();
|
||||
Lex_exact_charset_extended_collation_attrs_st::init();
|
||||
m_charset_order= CHARSET_TYPE_EMPTY;
|
||||
m_had_charset_exact= false;
|
||||
}
|
||||
void init(const Lex_exact_charset_opt_extended_collate &c)
|
||||
{
|
||||
Lex_opt_context_charset_st::init();
|
||||
Lex_exact_charset_extended_collation_attrs_st::init(c);
|
||||
m_charset_order= CHARSET_TYPE_EXACT;
|
||||
m_had_charset_exact= true;
|
||||
}
|
||||
bool is_empty() const
|
||||
{
|
||||
return Lex_opt_context_charset_st::is_empty() &&
|
||||
Lex_exact_charset_extended_collation_attrs_st::is_empty();
|
||||
}
|
||||
bool raise_if_charset_conflicts_with_default(
|
||||
const Lex_exact_charset_opt_extended_collate &def) const;
|
||||
CHARSET_INFO *resolved_to_context(const Charset_collation_context &ctx) const;
|
||||
bool merge_charset_default();
|
||||
bool merge_exact_charset(const Lex_exact_charset &cs);
|
||||
};
|
||||
|
||||
|
||||
class Lex_exact_charset_extended_collation_attrs:
|
||||
public Lex_exact_charset_extended_collation_attrs_st
|
||||
{
|
||||
@ -456,6 +617,23 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class Lex_extended_charset_extended_collation_attrs:
|
||||
public Lex_extended_charset_extended_collation_attrs_st
|
||||
{
|
||||
public:
|
||||
Lex_extended_charset_extended_collation_attrs()
|
||||
{
|
||||
init();
|
||||
}
|
||||
explicit Lex_extended_charset_extended_collation_attrs(
|
||||
const Lex_exact_charset_opt_extended_collate &c)
|
||||
{
|
||||
init(c);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
using Lex_column_charset_collation_attrs_st =
|
||||
Lex_exact_charset_extended_collation_attrs_st;
|
||||
|
||||
@ -463,4 +641,11 @@ using Lex_column_charset_collation_attrs =
|
||||
Lex_exact_charset_extended_collation_attrs;
|
||||
|
||||
|
||||
using Lex_table_charset_collation_attrs_st =
|
||||
Lex_extended_charset_extended_collation_attrs_st;
|
||||
|
||||
using Lex_table_charset_collation_attrs =
|
||||
Lex_extended_charset_extended_collation_attrs;
|
||||
|
||||
|
||||
#endif // LEX_CHARSET_INCLUDED
|
||||
|
@ -922,7 +922,7 @@ bool partition_info::vers_set_hist_part(THD *thd, uint *create_count)
|
||||
bool vers_create_partitions(THD *thd, TABLE_LIST* tl, uint num_parts)
|
||||
{
|
||||
bool result= true;
|
||||
HA_CREATE_INFO create_info;
|
||||
Table_specification_st create_info;
|
||||
Alter_info alter_info;
|
||||
partition_info *save_part_info= thd->work_part_info;
|
||||
Query_tables_list save_query_tables;
|
||||
|
@ -411,7 +411,7 @@ bool Sql_cmd_alter_table::execute(THD *thd)
|
||||
referenced from this structure will be modified.
|
||||
@todo move these into constructor...
|
||||
*/
|
||||
HA_CREATE_INFO create_info(lex->create_info);
|
||||
Table_specification_st create_info(lex->create_info);
|
||||
Alter_info alter_info(lex->alter_info, thd->mem_root);
|
||||
create_info.alter_info= &alter_info;
|
||||
privilege_t priv(NO_ACL);
|
||||
|
@ -56,6 +56,7 @@
|
||||
#include "sp_rcontext.h"
|
||||
#include "sp_cache.h"
|
||||
#include "sql_show.h" // append_identifier
|
||||
#include "sql_db.h" // get_default_db_collation
|
||||
#include "transaction.h"
|
||||
#include "sql_select.h" /* declares create_tmp_table() */
|
||||
#include "debug_sync.h"
|
||||
@ -8296,3 +8297,27 @@ THD_list_iterator *THD_list_iterator::iterator()
|
||||
{
|
||||
return &server_threads;
|
||||
}
|
||||
|
||||
|
||||
Charset_collation_context
|
||||
THD::charset_collation_context_alter_db(const char *db)
|
||||
{
|
||||
return Charset_collation_context(variables.collation_server,
|
||||
get_default_db_collation(this, db));
|
||||
}
|
||||
|
||||
|
||||
Charset_collation_context
|
||||
THD::charset_collation_context_create_table_in_db(const char *db)
|
||||
{
|
||||
CHARSET_INFO *cs= get_default_db_collation(this, db);
|
||||
return Charset_collation_context(cs, cs);
|
||||
}
|
||||
|
||||
|
||||
Charset_collation_context
|
||||
THD::charset_collation_context_alter_table(const TABLE_SHARE *s)
|
||||
{
|
||||
return Charset_collation_context(get_default_db_collation(this, s->db.str),
|
||||
s->table_charset);
|
||||
}
|
||||
|
@ -5521,6 +5521,19 @@ public:
|
||||
MY_UTF8_IS_UTF8MB3 : 0);
|
||||
}
|
||||
|
||||
Charset_collation_context
|
||||
charset_collation_context_create_db() const
|
||||
{
|
||||
return Charset_collation_context(variables.collation_server,
|
||||
variables.collation_server);
|
||||
}
|
||||
Charset_collation_context
|
||||
charset_collation_context_alter_db(const char *db);
|
||||
Charset_collation_context
|
||||
charset_collation_context_create_table_in_db(const char *db);
|
||||
Charset_collation_context
|
||||
charset_collation_context_alter_table(const TABLE_SHARE *s);
|
||||
|
||||
/**
|
||||
Save current lex to the output parameter and reset it to point to
|
||||
main_lex. This method is called from mysql_client_binlog_statement()
|
||||
@ -6140,6 +6153,7 @@ public:
|
||||
m_plock(NULL), exit_done(0),
|
||||
saved_tmp_table_share(0)
|
||||
{
|
||||
DBUG_ASSERT(create_info->default_table_charset);
|
||||
bzero(&ddl_log_state_create, sizeof(ddl_log_state_create));
|
||||
bzero(&ddl_log_state_rm, sizeof(ddl_log_state_rm));
|
||||
}
|
||||
|
@ -943,6 +943,7 @@ exit:
|
||||
int mysql_create_db(THD *thd, const LEX_CSTRING *db, DDL_options_st options,
|
||||
const Schema_specification_st *create_info)
|
||||
{
|
||||
DBUG_ASSERT(create_info->default_table_charset);
|
||||
/*
|
||||
As mysql_create_db_internal() may modify Db_create_info structure passed
|
||||
to it, we need to use a copy to make execution prepared statement- safe.
|
||||
@ -958,6 +959,7 @@ int mysql_create_db(THD *thd, const LEX_CSTRING *db, DDL_options_st options,
|
||||
bool mysql_alter_db(THD *thd, const LEX_CSTRING *db,
|
||||
const Schema_specification_st *create_info)
|
||||
{
|
||||
DBUG_ASSERT(create_info->default_table_charset);
|
||||
/*
|
||||
As mysql_alter_db_internal() may modify Db_create_info structure passed
|
||||
to it, we need to use a copy to make execution prepared statement- safe.
|
||||
|
@ -4408,6 +4408,23 @@ public:
|
||||
bool add_alter_list(LEX_CSTRING par_name, Virtual_column_info *expr,
|
||||
bool par_exists);
|
||||
bool add_alter_list(LEX_CSTRING name, LEX_CSTRING new_name, bool exists);
|
||||
bool add_alter_list_item_convert_to_charset(CHARSET_INFO *cs)
|
||||
{
|
||||
if (create_info.add_table_option_convert_charset(cs))
|
||||
return true;
|
||||
alter_info.flags|= ALTER_CONVERT_TO;
|
||||
return false;
|
||||
}
|
||||
bool
|
||||
add_alter_list_item_convert_to_charset(CHARSET_INFO *cs,
|
||||
const Lex_extended_collation_st &cl)
|
||||
{
|
||||
if (create_info.add_table_option_convert_charset(cs) ||
|
||||
create_info.add_table_option_convert_collation(cl))
|
||||
return true;
|
||||
alter_info.flags|= ALTER_CONVERT_TO;
|
||||
return false;
|
||||
}
|
||||
void set_command(enum_sql_command command,
|
||||
DDL_options_st options)
|
||||
{
|
||||
|
@ -43,9 +43,7 @@
|
||||
// mysql_alter_db,
|
||||
// check_db_dir_existence,
|
||||
// my_dbopt_cleanup
|
||||
#include "sql_table.h" // mysql_create_like_table,
|
||||
// mysql_create_table,
|
||||
// mysql_alter_table,
|
||||
#include "sql_table.h" // mysql_alter_table,
|
||||
// mysql_backup_table,
|
||||
// mysql_restore_table
|
||||
#include "sql_reload.h" // reload_acl_and_cache
|
||||
@ -4190,7 +4188,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
|
||||
*/
|
||||
{
|
||||
/* Prepare stack copies to be re-execution safe */
|
||||
HA_CREATE_INFO create_info;
|
||||
Table_specification_st create_info;
|
||||
Alter_info alter_info(lex->alter_info, thd->mem_root);
|
||||
|
||||
if (unlikely(thd->is_fatal_error)) /* out of memory creating alter_info */
|
||||
@ -4200,10 +4198,9 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
|
||||
if (check_one_table_access(thd, INDEX_ACL, all_tables))
|
||||
goto error; /* purecov: inspected */
|
||||
|
||||
bzero((char*) &create_info, sizeof(create_info));
|
||||
create_info.init();
|
||||
create_info.db_type= 0;
|
||||
create_info.row_type= ROW_TYPE_NOT_USED;
|
||||
create_info.default_table_charset= thd->variables.collation_database;
|
||||
create_info.alter_info= &alter_info;
|
||||
|
||||
WSREP_TO_ISOLATION_BEGIN(first_table->db.str, first_table->table_name.str, NULL);
|
||||
@ -5162,6 +5159,10 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
|
||||
&lex->name))
|
||||
break;
|
||||
|
||||
if ((res= lex->create_info.resolve_to_charset_collation_context(thd,
|
||||
thd->charset_collation_context_create_db())))
|
||||
break;
|
||||
|
||||
WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL);
|
||||
|
||||
res= mysql_create_db(thd, &lex->name,
|
||||
@ -5223,6 +5224,10 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
|
||||
if (prepare_db_action(thd, ALTER_ACL, db))
|
||||
break;
|
||||
|
||||
if ((res= lex->create_info.resolve_to_charset_collation_context(thd,
|
||||
thd->charset_collation_context_alter_db(lex->name.str))))
|
||||
break;
|
||||
|
||||
WSREP_TO_ISOLATION_BEGIN(db->str, NULL, NULL);
|
||||
|
||||
res= mysql_alter_db(thd, db, &lex->create_info);
|
||||
@ -10472,40 +10477,6 @@ bool parse_sql(THD *thd, Parser_state *parser_state,
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Check and merge "CHARACTER SET cs [ COLLATE cl ]" clause
|
||||
|
||||
@param cs character set pointer.
|
||||
@param cl collation pointer.
|
||||
|
||||
Check if collation "cl" is applicable to character set "cs".
|
||||
|
||||
If "cl" is NULL (e.g. when COLLATE clause is not specified),
|
||||
then simply "cs" is returned.
|
||||
|
||||
@return Error status.
|
||||
@retval NULL, if "cl" is not applicable to "cs".
|
||||
@retval pointer to merged CHARSET_INFO on success.
|
||||
*/
|
||||
|
||||
|
||||
CHARSET_INFO*
|
||||
merge_charset_and_collation(CHARSET_INFO *cs, CHARSET_INFO *cl)
|
||||
{
|
||||
if (cl)
|
||||
{
|
||||
if (!my_charset_same(cs, cl))
|
||||
{
|
||||
my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0), cl->coll_name.str,
|
||||
cs->cs_name.str);
|
||||
return NULL;
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
return cs;
|
||||
}
|
||||
|
||||
void LEX::mark_first_table_as_inserting()
|
||||
{
|
||||
TABLE_LIST *t= first_select_lex()->table_list.first;
|
||||
|
@ -78,7 +78,6 @@ bool check_string_char_length(const LEX_CSTRING *str, uint err_msg,
|
||||
size_t max_char_length, CHARSET_INFO *cs,
|
||||
bool no_error);
|
||||
bool check_ident_length(const LEX_CSTRING *ident);
|
||||
CHARSET_INFO* merge_charset_and_collation(CHARSET_INFO *cs, CHARSET_INFO *cl);
|
||||
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);
|
||||
|
@ -195,7 +195,8 @@ static bool check_exchange_partition(TABLE *table, TABLE *part_table)
|
||||
bool compare_table_with_partition(THD *thd, TABLE *table, TABLE *part_table,
|
||||
partition_element *part_elem, uint part_id)
|
||||
{
|
||||
HA_CREATE_INFO table_create_info, part_create_info;
|
||||
HA_CREATE_INFO table_create_info;
|
||||
Table_specification_st part_create_info;
|
||||
Alter_info part_alter_info;
|
||||
Alter_table_ctx part_alter_ctx; // Not used
|
||||
DBUG_ENTER("compare_table_with_partition");
|
||||
|
136
sql/sql_table.cc
136
sql/sql_table.cc
@ -3874,38 +3874,6 @@ bool validate_comment_length(THD *thd, LEX_CSTRING *comment, size_t max_len,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Set table default charset, if not set
|
||||
|
||||
SYNOPSIS
|
||||
set_table_default_charset()
|
||||
create_info Table create information
|
||||
|
||||
DESCRIPTION
|
||||
If the table character set was not given explicitly,
|
||||
let's fetch the database default character set and
|
||||
apply it to the table.
|
||||
*/
|
||||
|
||||
static void set_table_default_charset(THD *thd, HA_CREATE_INFO *create_info,
|
||||
const LEX_CSTRING &db)
|
||||
{
|
||||
/*
|
||||
If the table character set was not given explicitly,
|
||||
let's fetch the database default character set and
|
||||
apply it to the table.
|
||||
*/
|
||||
if (!create_info->default_table_charset)
|
||||
{
|
||||
Schema_specification_st db_info;
|
||||
|
||||
load_db_opt_by_name(thd, db.str, &db_info);
|
||||
|
||||
create_info->default_table_charset= db_info.default_table_charset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Extend long VARCHAR fields to blob & prepare field if it's a blob
|
||||
|
||||
@ -4064,14 +4032,14 @@ handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db,
|
||||
handler *file;
|
||||
DBUG_ENTER("mysql_create_frm_image");
|
||||
|
||||
DBUG_ASSERT(create_info->default_table_charset);
|
||||
|
||||
if (!alter_info->create_list.elements)
|
||||
{
|
||||
my_error(ER_TABLE_MUST_HAVE_COLUMNS, MYF(0));
|
||||
DBUG_RETURN(NULL);
|
||||
}
|
||||
|
||||
set_table_default_charset(thd, create_info, db);
|
||||
|
||||
db_options= create_info->table_options_with_row_type();
|
||||
|
||||
if (unlikely(!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
|
||||
@ -4345,6 +4313,7 @@ err:
|
||||
@retval -1 table existed but IF NOT EXISTS was used
|
||||
*/
|
||||
|
||||
static
|
||||
int create_table_impl(THD *thd,
|
||||
DDL_LOG_STATE *ddl_log_state_create,
|
||||
DDL_LOG_STATE *ddl_log_state_rm,
|
||||
@ -4365,6 +4334,8 @@ int create_table_impl(THD *thd,
|
||||
DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d path: %s",
|
||||
db.str, table_name.str, internal_tmp_table, path.str));
|
||||
|
||||
DBUG_ASSERT(create_info->default_table_charset);
|
||||
|
||||
/* Easy check for ddl logging if we are creating a temporary table */
|
||||
if (create_info->tmp_table())
|
||||
{
|
||||
@ -4703,6 +4674,8 @@ int mysql_create_table_no_lock(THD *thd,
|
||||
LEX_CSTRING cpath;
|
||||
LEX_CUSTRING frm= {0,0};
|
||||
|
||||
DBUG_ASSERT(create_info->default_table_charset);
|
||||
|
||||
if (create_info->tmp_table())
|
||||
path_length= build_tmptable_filename(thd, path, sizeof(path));
|
||||
else
|
||||
@ -4771,6 +4744,8 @@ int mysql_create_table_no_lock(THD *thd,
|
||||
close of thread tables.
|
||||
*/
|
||||
|
||||
|
||||
static
|
||||
bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
|
||||
Table_specification_st *create_info,
|
||||
Alter_info *alter_info)
|
||||
@ -4784,6 +4759,8 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
|
||||
bool result;
|
||||
DBUG_ENTER("mysql_create_table");
|
||||
|
||||
DBUG_ASSERT(create_info->default_table_charset);
|
||||
|
||||
DBUG_ASSERT(create_table == thd->lex->query_tables);
|
||||
|
||||
bzero(&ddl_log_state_create, sizeof(ddl_log_state_create));
|
||||
@ -5222,6 +5199,7 @@ mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
|
||||
TRUE error
|
||||
*/
|
||||
|
||||
static
|
||||
bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
|
||||
TABLE_LIST* src_table,
|
||||
Table_specification_st *create_info)
|
||||
@ -5296,6 +5274,14 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
|
||||
local_create_info.db_type= src_table->table->s->db_type();
|
||||
local_create_info.row_type= src_table->table->s->row_type;
|
||||
local_create_info.alter_info= &local_alter_info;
|
||||
/*
|
||||
This statement:
|
||||
CREATE TABLE t1 LIKE t2
|
||||
does not support table charset/collation clauses.
|
||||
No needs to copy. Assert they are empty.
|
||||
*/
|
||||
DBUG_ASSERT(create_info->default_charset_collation.is_empty());
|
||||
DBUG_ASSERT(create_info->convert_charset_collation.is_empty());
|
||||
if (mysql_prepare_alter_table(thd, src_table->table, &local_create_info,
|
||||
&local_alter_info, &local_alter_ctx))
|
||||
goto err;
|
||||
@ -7949,7 +7935,7 @@ void append_drop_column(THD *thd, String *str, Field *field)
|
||||
|
||||
bool
|
||||
mysql_prepare_alter_table(THD *thd, TABLE *table,
|
||||
HA_CREATE_INFO *create_info,
|
||||
Table_specification_st *create_info,
|
||||
Alter_info *alter_info,
|
||||
Alter_table_ctx *alter_ctx)
|
||||
{
|
||||
@ -8015,8 +8001,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
|
||||
create_info->max_rows= table->s->max_rows;
|
||||
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
|
||||
create_info->avg_row_length= table->s->avg_row_length;
|
||||
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
|
||||
create_info->default_table_charset= table->s->table_charset;
|
||||
|
||||
if (create_info->resolve_to_charset_collation_context(thd,
|
||||
thd->charset_collation_context_alter_table(table->s)))
|
||||
DBUG_RETURN(true);
|
||||
|
||||
if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
|
||||
{
|
||||
/* Table has an autoincrement, copy value to new table */
|
||||
@ -9774,7 +9763,7 @@ static uint64 get_start_alter_id(THD *thd)
|
||||
|
||||
bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
|
||||
const LEX_CSTRING *new_name,
|
||||
HA_CREATE_INFO *create_info,
|
||||
Table_specification_st *create_info,
|
||||
TABLE_LIST *table_list,
|
||||
Alter_info *alter_info,
|
||||
uint order_num, ORDER *order, bool ignore,
|
||||
@ -10367,7 +10356,7 @@ do_continue:;
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
set_table_default_charset(thd, create_info, alter_ctx.db);
|
||||
DBUG_ASSERT(create_info->default_table_charset);
|
||||
|
||||
if (create_info->check_fields(thd, alter_info,
|
||||
table_list->table_name, table_list->db) ||
|
||||
@ -11787,7 +11776,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
|
||||
|
||||
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool table_copy)
|
||||
{
|
||||
HA_CREATE_INFO create_info;
|
||||
Table_specification_st create_info;
|
||||
Alter_info alter_info;
|
||||
TABLE_LIST *next_table= table_list->next_global;
|
||||
DBUG_ENTER("mysql_recreate_table");
|
||||
@ -11799,9 +11788,8 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool table_copy)
|
||||
/* hide following tables from open_tables() */
|
||||
table_list->next_global= NULL;
|
||||
|
||||
bzero((char*) &create_info, sizeof(create_info));
|
||||
create_info.init();
|
||||
create_info.row_type=ROW_TYPE_NOT_USED;
|
||||
create_info.default_table_charset=default_charset_info;
|
||||
create_info.alter_info= &alter_info;
|
||||
/* Force alter table to recreate table */
|
||||
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
|
||||
@ -12058,6 +12046,11 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
|
||||
|
||||
const bool used_engine= lex->create_info.used_fields & HA_CREATE_USED_ENGINE;
|
||||
DBUG_ASSERT((m_storage_engine_name.str != NULL) == used_engine);
|
||||
|
||||
if (lex->create_info.resolve_to_charset_collation_context(thd,
|
||||
thd->charset_collation_context_create_table_in_db(first_table->db.str)))
|
||||
DBUG_RETURN(true);
|
||||
|
||||
if (used_engine)
|
||||
{
|
||||
if (resolve_storage_engine_with_error(thd, &lex->create_info.db_type,
|
||||
@ -12130,19 +12123,9 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
|
||||
*/
|
||||
if (!(create_info.used_fields & HA_CREATE_USED_ENGINE))
|
||||
create_info.use_default_db_type(thd);
|
||||
/*
|
||||
If we are using SET CHARSET without DEFAULT, add an implicit
|
||||
DEFAULT to not confuse old users. (This may change).
|
||||
*/
|
||||
if ((create_info.used_fields &
|
||||
(HA_CREATE_USED_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) ==
|
||||
HA_CREATE_USED_CHARSET)
|
||||
{
|
||||
create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
|
||||
create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
|
||||
create_info.default_table_charset= create_info.alter_table_convert_to_charset;
|
||||
create_info.alter_table_convert_to_charset= 0;
|
||||
}
|
||||
|
||||
DBUG_ASSERT(!(create_info.used_fields & HA_CREATE_USED_CHARSET));
|
||||
DBUG_ASSERT(create_info.convert_charset_collation.is_empty());
|
||||
|
||||
/*
|
||||
If we are a slave, we should add OR REPLACE if we don't have
|
||||
@ -12368,3 +12351,46 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
|
||||
end_with_restore_list:
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
|
||||
bool HA_CREATE_INFO::
|
||||
resolve_to_charset_collation_context(THD *thd,
|
||||
const Lex_table_charset_collation_attrs_st &default_cscl_arg,
|
||||
const Lex_table_charset_collation_attrs_st &convert_cscl,
|
||||
const Charset_collation_context &ctx)
|
||||
{
|
||||
/*
|
||||
If CONVERT TO clauses are specified only (without table default clauses),
|
||||
then we copy CONVERT TO clauses to default clauses, so e.g:
|
||||
CONVERT TO CHARACTER SET utf8mb4
|
||||
means
|
||||
CONVERT TO CHARACTER SET utf8mb4, DEFAULT CHARACTER SET utf8mb4
|
||||
*/
|
||||
Lex_table_charset_collation_attrs_st default_cscl=
|
||||
!convert_cscl.is_empty() && default_cscl_arg.is_empty() ?
|
||||
convert_cscl : default_cscl_arg;
|
||||
|
||||
if (default_cscl.is_empty())
|
||||
default_table_charset= ctx.collate_default().charset_info();
|
||||
else
|
||||
{
|
||||
// Make sure we don't do double resolution in direct SQL execution
|
||||
DBUG_ASSERT(!default_table_charset || thd->stmt_arena->is_stmt_execute());
|
||||
if (!(default_table_charset=
|
||||
default_cscl.resolved_to_context(ctx)))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (convert_cscl.is_empty())
|
||||
alter_table_convert_to_charset= NULL;
|
||||
else
|
||||
{
|
||||
// Make sure we don't do double resolution in direct SQL execution
|
||||
DBUG_ASSERT(!alter_table_convert_to_charset ||
|
||||
thd->stmt_arena->is_stmt_execute());
|
||||
if (!(alter_table_convert_to_charset=
|
||||
convert_cscl.resolved_to_context(ctx)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <my_sys.h> // pthread_mutex_t
|
||||
#include "m_string.h" // LEX_CUSTRING
|
||||
#include "lex_charset.h"
|
||||
|
||||
#define ERROR_INJECT(code) \
|
||||
((DBUG_IF("crash_" code) && (DBUG_SUICIDE(), 0)) || \
|
||||
@ -90,9 +91,6 @@ void build_lower_case_table_filename(char *buff, size_t bufflen,
|
||||
const LEX_CSTRING *table,
|
||||
uint flags);
|
||||
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen);
|
||||
bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
|
||||
Table_specification_st *create_info,
|
||||
Alter_info *alter_info);
|
||||
bool add_keyword_to_query(THD *thd, String *result, const LEX_CSTRING *keyword,
|
||||
const LEX_CSTRING *add);
|
||||
|
||||
@ -156,14 +154,14 @@ int mysql_discard_or_import_tablespace(THD *thd,
|
||||
bool discard);
|
||||
|
||||
bool mysql_prepare_alter_table(THD *thd, TABLE *table,
|
||||
HA_CREATE_INFO *create_info,
|
||||
Table_specification_st *create_info,
|
||||
Alter_info *alter_info,
|
||||
Alter_table_ctx *alter_ctx);
|
||||
bool mysql_trans_prepare_alter_copy_data(THD *thd);
|
||||
bool mysql_trans_commit_alter_copy_data(THD *thd);
|
||||
bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
|
||||
const LEX_CSTRING *new_name,
|
||||
HA_CREATE_INFO *create_info,
|
||||
Table_specification_st *create_info,
|
||||
TABLE_LIST *table_list,
|
||||
Alter_info *alter_info,
|
||||
uint order_num, ORDER *order, bool ignore,
|
||||
@ -173,9 +171,6 @@ bool mysql_compare_tables(TABLE *table,
|
||||
HA_CREATE_INFO *create_info,
|
||||
bool *metadata_equal);
|
||||
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool table_copy);
|
||||
bool mysql_create_like_table(THD *thd, TABLE_LIST *table,
|
||||
TABLE_LIST *src_table,
|
||||
Table_specification_st *create_info);
|
||||
bool mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
|
||||
const LEX_CSTRING *old_name, const LEX_CSTRING *new_db,
|
||||
const LEX_CSTRING *new_name, LEX_CUSTRING *id,
|
||||
|
@ -2369,7 +2369,6 @@ create:
|
||||
If the table exists, we should either not create it or replace it
|
||||
*/
|
||||
lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
|
||||
lex->create_info.default_table_charset= NULL;
|
||||
lex->name= null_clex_str;
|
||||
lex->create_last_non_select_table= lex->last_table();
|
||||
lex->inc_select_stack_outer_barrier();
|
||||
@ -2512,9 +2511,7 @@ create:
|
||||
}
|
||||
| create_or_replace DATABASE opt_if_not_exists ident
|
||||
{
|
||||
Lex->create_info.default_table_charset= NULL;
|
||||
Lex->create_info.schema_comment= NULL;
|
||||
Lex->create_info.used_fields= 0;
|
||||
Lex->create_info.init();
|
||||
}
|
||||
opt_create_database_options
|
||||
{
|
||||
@ -5533,17 +5530,9 @@ default_charset:
|
||||
default_collation:
|
||||
opt_default COLLATE_SYM opt_equal collation_name_or_default
|
||||
{
|
||||
HA_CREATE_INFO *cinfo= &Lex->create_info;
|
||||
bool is_exact= $4.type() == Lex_extended_collation_st::TYPE_EXACT;
|
||||
CHARSET_INFO *cl= is_exact ? $4.charset_info() : NULL;
|
||||
if (unlikely((cinfo->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) &&
|
||||
cinfo->default_table_charset && cl &&
|
||||
!(cl= merge_charset_and_collation(cinfo->default_table_charset,
|
||||
cl))))
|
||||
Table_specification_st *cinfo= &Lex->create_info;
|
||||
if (unlikely(cinfo->add_table_option_default_collation($4)))
|
||||
MYSQL_YYABORT;
|
||||
|
||||
Lex->create_info.default_table_charset= cl;
|
||||
Lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
|
||||
}
|
||||
;
|
||||
|
||||
@ -6955,9 +6944,7 @@ alter:
|
||||
}
|
||||
| ALTER DATABASE ident_or_empty
|
||||
{
|
||||
Lex->create_info.default_table_charset= NULL;
|
||||
Lex->create_info.schema_comment= NULL;
|
||||
Lex->create_info.used_fields= 0;
|
||||
Lex->create_info.init();
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
@ -6973,8 +6960,7 @@ alter:
|
||||
}
|
||||
| ALTER DATABASE COMMENT_SYM opt_equal TEXT_STRING_sys
|
||||
{
|
||||
Lex->create_info.default_table_charset= NULL;
|
||||
Lex->create_info.used_fields= 0;
|
||||
Lex->create_info.init();
|
||||
Lex->create_info.schema_comment= thd->make_clex_string($5);
|
||||
Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT;
|
||||
}
|
||||
@ -7619,29 +7605,14 @@ alter_list_item:
|
||||
}
|
||||
| CONVERT_SYM TO_SYM charset charset_name_or_default
|
||||
{
|
||||
if (!$4)
|
||||
{
|
||||
$4= thd->variables.collation_database;
|
||||
}
|
||||
if (unlikely(Lex->create_info.add_alter_list_item_convert_to_charset($4)))
|
||||
if (Lex->add_alter_list_item_convert_to_charset($4))
|
||||
MYSQL_YYABORT;
|
||||
Lex->alter_info.flags|= ALTER_CONVERT_TO;
|
||||
}
|
||||
| CONVERT_SYM TO_SYM charset charset_name_or_default
|
||||
COLLATE_SYM collation_name_or_default
|
||||
{
|
||||
if (!$4)
|
||||
{
|
||||
$4= thd->variables.collation_database;
|
||||
}
|
||||
bool is_exact= $6.type() == Lex_extended_collation_st::TYPE_EXACT;
|
||||
CHARSET_INFO *cl= is_exact ? $6.charset_info() : $4;
|
||||
if (unlikely(!my_charset_same($4,cl)))
|
||||
my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0),
|
||||
cl->coll_name.str, $4->cs_name.str));
|
||||
if (unlikely(Lex->create_info.add_alter_list_item_convert_to_charset(cl)))
|
||||
if (Lex->add_alter_list_item_convert_to_charset($4, $6))
|
||||
MYSQL_YYABORT;
|
||||
Lex->alter_info.flags|= ALTER_CONVERT_TO;
|
||||
}
|
||||
| create_table_options_space_separated
|
||||
{
|
||||
|
17
sql/table.cc
17
sql/table.cc
@ -45,6 +45,7 @@
|
||||
#include "ha_sequence.h"
|
||||
#include "sql_show.h"
|
||||
#include "opt_trace.h"
|
||||
#include "sql_db.h" // get_default_db_collation
|
||||
|
||||
/* For MySQL 5.7 virtual fields */
|
||||
#define MYSQL57_GENERATED_FIELD 128
|
||||
@ -3503,6 +3504,19 @@ int TABLE_SHARE::init_from_sql_statement_string(THD *thd, bool write,
|
||||
else
|
||||
thd->set_n_backup_active_arena(arena, &backup);
|
||||
|
||||
/*
|
||||
THD::reset_db() does not set THD::db_charset,
|
||||
so it keeps pointing to the character set and collation
|
||||
of the current database, rather than the database of the
|
||||
new initialized table. After reset_db() the result of
|
||||
get_default_db_collation() can be wrong. The latter is
|
||||
used inside charset_collation_context_create_table_in_db().
|
||||
Let's initialize ctx before calling reset_db().
|
||||
This makes sure the db.opt file to be loaded properly when needed.
|
||||
*/
|
||||
Charset_collation_context
|
||||
ctx(thd->charset_collation_context_create_table_in_db(db.str));
|
||||
|
||||
thd->reset_db(&db);
|
||||
lex_start(thd);
|
||||
|
||||
@ -3510,6 +3524,9 @@ int TABLE_SHARE::init_from_sql_statement_string(THD *thd, bool write,
|
||||
sql_unusable_for_discovery(thd, hton, sql_copy))))
|
||||
goto ret;
|
||||
|
||||
if (thd->lex->create_info.resolve_to_charset_collation_context(thd, ctx))
|
||||
DBUG_RETURN(true);
|
||||
|
||||
thd->lex->create_info.db_type= hton;
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
thd->work_part_info= 0; // For partitioning
|
||||
|
Loading…
x
Reference in New Issue
Block a user