MDEV-10865 COLLATE keyword doesn't work in PREPARE query
Fixing applying the COLLATE clause to a parameter caused an error error: COLLATION '...' is not valid for CHARACTER SET 'binary' Fix: - Changing the collation derivation for a non-prepared Item_param to DERIVATION_IGNORABLE. - Allowing to apply any COLLATE clause to expressions with DERIVATION_IGNORABLE. This includes: 1. A non-prepared Item_param 2. An explicit NULL 3. Expressions derived from #1 and #2 For example: SELECT ? COLLATE utf8mb_unicode_ci; SELECT NULL COLLATE utf8mb_unicode_ci; SELECT CONCAT(?) COLLATE utf8mb_unicode_ci; SELECT CONCAT(NULL) COLLATE utf8mb_unicode_ci - Additional change: preserving the collation of an expression when the expression gets assigned to a PS parameter and evaluates to SQL NULL. Before this change, the collation of the parameter was erroneously set to &my_charset_binary. - Additional change: removing the multiplication to mbmaxlen from the fix_char_length_ulonglong() argument, because the multiplication already happens inside fix_char_length_ulonglong(). This fixes a too large column size created for a COLLATE clause.
This commit is contained in:
parent
c91ec6a5c1
commit
f6989d1767
@ -3716,3 +3716,103 @@ DROP PROCEDURE p;
|
||||
#
|
||||
# End of 10.9 tests
|
||||
#
|
||||
#
|
||||
# Start of 10.11 tests
|
||||
#
|
||||
#
|
||||
# MDEV-10865 COLLATE keyword doesn't work in PREPARE query
|
||||
#
|
||||
SET NAMES utf8mb4;
|
||||
#
|
||||
# A context collation and an explicit NULL
|
||||
#
|
||||
SELECT NULL COLLATE uca1400_ai_ci;
|
||||
ERROR HY000: 'NULL' is not allowed in this context
|
||||
SELECT CONCAT(NULL) COLLATE uca1400_ai_ci;
|
||||
ERROR HY000: 'NULL' is not allowed in this context
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT NULL COLLATE uca1400_ai_ci AS c1';
|
||||
ERROR HY000: 'NULL' is not allowed in this context
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT CONCAT(NULL) COLLATE uca1400_ai_ci AS c1';
|
||||
ERROR HY000: 'NULL' is not allowed in this context
|
||||
#
|
||||
# A context collation and a parameter bound to NULL
|
||||
#
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
|
||||
EXECUTE stmt USING NULL;
|
||||
ERROR HY000: 'NULL' is not allowed in this context
|
||||
EXECUTE stmt USING CONCAT(NULL);
|
||||
ERROR HY000: 'NULL' is not allowed in this context
|
||||
EXECUTE stmt USING NULL COLLATE uca1400_ai_ci;
|
||||
ERROR HY000: 'NULL' is not allowed in this context
|
||||
EXECUTE stmt USING CONCAT(NULL) COLLATE uca1400_ai_ci;
|
||||
ERROR HY000: 'NULL' is not allowed in this context
|
||||
#
|
||||
# A context collation and CONVERT(NULL USING ...)
|
||||
#
|
||||
EXECUTE stmt USING CONVERT(NULL USING utf8mb4);
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` char(0) CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
EXECUTE stmt USING CONVERT(NULL USING utf8mb4) COLLATE uca1400_ai_ci;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` char(0) CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
EXECUTE stmt USING CONVERT(NULL USING binary);
|
||||
ERROR 42000: COLLATION 'uca1400_ai_ci' is not valid for CHARACTER SET 'binary'
|
||||
EXECUTE stmt USING CONVERT(NULL USING latin1);
|
||||
ERROR 42000: COLLATION 'uca1400_ai_ci' is not valid for CHARACTER SET 'latin1'
|
||||
#
|
||||
# A context collation and an expression with a parameter
|
||||
# whose character does not get resolved when bound to a not-NULL value
|
||||
#
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT LEFT(NULL,?) COLLATE uca1400_ai_ci AS c1';
|
||||
EXECUTE stmt USING NULL;
|
||||
ERROR HY000: 'NULL' is not allowed in this context
|
||||
#
|
||||
# A context collation and an expression with a parameter
|
||||
# whose character set gets resolved when bound to a not-NULL value
|
||||
#
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
|
||||
EXECUTE stmt USING 1;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
|
||||
EXECUTE stmt USING _binary'test';
|
||||
ERROR 42000: COLLATION 'uca1400_ai_ci' is not valid for CHARACTER SET 'binary'
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
|
||||
EXECUTE stmt USING 'test';
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
|
||||
EXECUTE stmt USING 'test' COLLATE utf8mb4_bin;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
|
||||
EXECUTE stmt USING _latin1'test' COLLATE latin1_bin;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 10.11 tests
|
||||
#
|
||||
|
@ -401,3 +401,103 @@ DROP PROCEDURE p;
|
||||
--echo #
|
||||
--echo # End of 10.9 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # Start of 10.11 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-10865 COLLATE keyword doesn't work in PREPARE query
|
||||
--echo #
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
--echo #
|
||||
--echo # A context collation and an explicit NULL
|
||||
--echo #
|
||||
|
||||
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||
SELECT NULL COLLATE uca1400_ai_ci;
|
||||
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||
SELECT CONCAT(NULL) COLLATE uca1400_ai_ci;
|
||||
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT NULL COLLATE uca1400_ai_ci AS c1';
|
||||
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT CONCAT(NULL) COLLATE uca1400_ai_ci AS c1';
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # A context collation and a parameter bound to NULL
|
||||
--echo #
|
||||
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
|
||||
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||
EXECUTE stmt USING NULL;
|
||||
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||
EXECUTE stmt USING CONCAT(NULL);
|
||||
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||
EXECUTE stmt USING NULL COLLATE uca1400_ai_ci;
|
||||
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||
EXECUTE stmt USING CONCAT(NULL) COLLATE uca1400_ai_ci;
|
||||
|
||||
--echo #
|
||||
--echo # A context collation and CONVERT(NULL USING ...)
|
||||
--echo #
|
||||
|
||||
EXECUTE stmt USING CONVERT(NULL USING utf8mb4);
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
EXECUTE stmt USING CONVERT(NULL USING utf8mb4) COLLATE uca1400_ai_ci;
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--error ER_COLLATION_CHARSET_MISMATCH
|
||||
EXECUTE stmt USING CONVERT(NULL USING binary);
|
||||
|
||||
--error ER_COLLATION_CHARSET_MISMATCH
|
||||
EXECUTE stmt USING CONVERT(NULL USING latin1);
|
||||
|
||||
--echo #
|
||||
--echo # A context collation and an expression with a parameter
|
||||
--echo # whose character does not get resolved when bound to a not-NULL value
|
||||
--echo #
|
||||
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT LEFT(NULL,?) COLLATE uca1400_ai_ci AS c1';
|
||||
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||
EXECUTE stmt USING NULL;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # A context collation and an expression with a parameter
|
||||
--echo # whose character set gets resolved when bound to a not-NULL value
|
||||
--echo #
|
||||
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
|
||||
EXECUTE stmt USING 1;
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
|
||||
--error ER_COLLATION_CHARSET_MISMATCH
|
||||
EXECUTE stmt USING _binary'test';
|
||||
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
|
||||
EXECUTE stmt USING 'test';
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
|
||||
EXECUTE stmt USING 'test' COLLATE utf8mb4_bin;
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
|
||||
EXECUTE stmt USING _latin1'test' COLLATE latin1_bin;
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.11 tests
|
||||
--echo #
|
||||
|
@ -3024,3 +3024,88 @@ HEX(DATE_FORMAT(TIME'11:22:33',@format))
|
||||
#
|
||||
# End of 10.4 tests
|
||||
#
|
||||
#
|
||||
# Start of 10.11 tests
|
||||
#
|
||||
#
|
||||
# MDEV-10865 COLLATE keyword doesn't work in PREPARE query
|
||||
#
|
||||
#
|
||||
# The collation is not applicable to the PS parameter
|
||||
#
|
||||
SET NAMES utf8mb4;
|
||||
CREATE TABLE t1 (
|
||||
c1 varchar(500) COLLATE utf32_unicode_ci NOT NULL
|
||||
);
|
||||
INSERT INTO t1 VALUES ('jj');
|
||||
PREPARE stmt FROM 'SELECT * FROM t1 WHERE c1 LIKE ? COLLATE utf32_unicode_ci';
|
||||
EXECUTE stmt USING 'jj';
|
||||
ERROR 42000: COLLATION 'utf32_unicode_ci' is not valid for CHARACTER SET 'utf8mb4'
|
||||
DROP TABLE t1;
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE utf32_unicode_ci AS c1';
|
||||
EXECUTE stmt USING 'test';
|
||||
ERROR 42000: COLLATION 'utf32_unicode_ci' is not valid for CHARACTER SET 'utf8mb4'
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT CONCAT(?) COLLATE utf32_unicode_ci AS c1';
|
||||
EXECUTE stmt USING 'test';
|
||||
ERROR 42000: COLLATION 'utf32_unicode_ci' is not valid for CHARACTER SET 'utf8mb4'
|
||||
CREATE TABLE t1 AS SELECT NULL COLLATE utf32_unicode_ci AS c1;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` char(0) CHARACTER SET utf32 COLLATE utf32_unicode_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 AS SELECT CONCAT(NULL) COLLATE utf32_unicode_ci AS c1;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` char(0) CHARACTER SET utf32 COLLATE utf32_unicode_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# The collation is applicable to the PS parameter
|
||||
#
|
||||
SET NAMES utf8mb4, collation_connection=utf32_general_ci;
|
||||
CREATE TABLE t1 (
|
||||
c1 varchar(500) COLLATE utf32_unicode_ci NOT NULL
|
||||
);
|
||||
INSERT INTO t1 VALUES ('jj');
|
||||
PREPARE stmt FROM 'SELECT * FROM t1 WHERE c1 LIKE ? COLLATE utf32_unicode_ci';
|
||||
EXECUTE stmt USING 'jj';
|
||||
c1
|
||||
jj
|
||||
DROP TABLE t1;
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE utf32_unicode_ci AS c1';
|
||||
EXECUTE stmt USING 'test';
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` varchar(4) CHARACTER SET utf32 COLLATE utf32_unicode_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT CONCAT(?) COLLATE utf32_unicode_ci AS c1';
|
||||
EXECUTE stmt USING 'test';
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` varchar(4) CHARACTER SET utf32 COLLATE utf32_unicode_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 AS SELECT NULL COLLATE utf32_unicode_ci AS c1;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` char(0) CHARACTER SET utf32 COLLATE utf32_unicode_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 AS SELECT CONCAT(NULL) COLLATE utf32_unicode_ci AS c1;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` char(0) CHARACTER SET utf32 COLLATE utf32_unicode_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
SET NAMES utf8mb4;
|
||||
#
|
||||
# End of 10.11 tests
|
||||
#
|
||||
|
@ -1167,4 +1167,80 @@ SELECT HEX(DATE_FORMAT(TIME'11:22:33',@format));
|
||||
--echo # End of 10.4 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # Start of 10.11 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-10865 COLLATE keyword doesn't work in PREPARE query
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # The collation is not applicable to the PS parameter
|
||||
--echo #
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
CREATE TABLE t1 (
|
||||
c1 varchar(500) COLLATE utf32_unicode_ci NOT NULL
|
||||
);
|
||||
INSERT INTO t1 VALUES ('jj');
|
||||
PREPARE stmt FROM 'SELECT * FROM t1 WHERE c1 LIKE ? COLLATE utf32_unicode_ci';
|
||||
--error ER_COLLATION_CHARSET_MISMATCH
|
||||
EXECUTE stmt USING 'jj';
|
||||
DROP TABLE t1;
|
||||
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE utf32_unicode_ci AS c1';
|
||||
--error ER_COLLATION_CHARSET_MISMATCH
|
||||
EXECUTE stmt USING 'test';
|
||||
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT CONCAT(?) COLLATE utf32_unicode_ci AS c1';
|
||||
--error ER_COLLATION_CHARSET_MISMATCH
|
||||
EXECUTE stmt USING 'test';
|
||||
|
||||
CREATE TABLE t1 AS SELECT NULL COLLATE utf32_unicode_ci AS c1;
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 AS SELECT CONCAT(NULL) COLLATE utf32_unicode_ci AS c1;
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # The collation is applicable to the PS parameter
|
||||
--echo #
|
||||
|
||||
SET NAMES utf8mb4, collation_connection=utf32_general_ci;
|
||||
CREATE TABLE t1 (
|
||||
c1 varchar(500) COLLATE utf32_unicode_ci NOT NULL
|
||||
);
|
||||
INSERT INTO t1 VALUES ('jj');
|
||||
PREPARE stmt FROM 'SELECT * FROM t1 WHERE c1 LIKE ? COLLATE utf32_unicode_ci';
|
||||
EXECUTE stmt USING 'jj';
|
||||
DROP TABLE t1;
|
||||
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE utf32_unicode_ci AS c1';
|
||||
EXECUTE stmt USING 'test';
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT CONCAT(?) COLLATE utf32_unicode_ci AS c1';
|
||||
EXECUTE stmt USING 'test';
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 AS SELECT NULL COLLATE utf32_unicode_ci AS c1;
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 AS SELECT CONCAT(NULL) COLLATE utf32_unicode_ci AS c1;
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.11 tests
|
||||
--echo #
|
||||
|
||||
--enable_service_connection
|
||||
|
@ -4182,24 +4182,6 @@ DROP TABLE t1;
|
||||
# End of 10.2 tests
|
||||
#
|
||||
#
|
||||
# Start of 10.5 tests
|
||||
#
|
||||
#
|
||||
# MDEV-24584 Selecting INT column with COLLATE utf8mb4_general_ci throws an error
|
||||
#
|
||||
SET NAMES utf8mb4;
|
||||
SELECT 1 COLLATE utf8mb4_general_ci;
|
||||
1 COLLATE utf8mb4_general_ci
|
||||
1
|
||||
SELECT 1 COLLATE utf8mb4_bin;
|
||||
1 COLLATE utf8mb4_bin
|
||||
1
|
||||
SELECT 1 COLLATE latin1_swedish_ci;
|
||||
ERROR 42000: COLLATION 'latin1_swedish_ci' is not valid for CHARACTER SET 'utf8mb4'
|
||||
#
|
||||
# End of 10.5 tests
|
||||
#
|
||||
#
|
||||
# Start of 10.6 tests
|
||||
#
|
||||
#
|
||||
@ -4227,3 +4209,67 @@ DROP TABLE t1;
|
||||
#
|
||||
# End of 10.6 tests
|
||||
#
|
||||
#
|
||||
# Start of 10.11 tests
|
||||
#
|
||||
#
|
||||
# MDEV-24584 Selecting INT column with COLLATE utf8mb4_general_ci throws an error
|
||||
#
|
||||
SET NAMES utf8mb4;
|
||||
SELECT 1 COLLATE utf8mb4_general_ci;
|
||||
1 COLLATE utf8mb4_general_ci
|
||||
1
|
||||
SELECT 1 COLLATE utf8mb4_bin;
|
||||
1 COLLATE utf8mb4_bin
|
||||
1
|
||||
SELECT 1 COLLATE latin1_swedish_ci;
|
||||
ERROR 42000: COLLATION 'latin1_swedish_ci' is not valid for CHARACTER SET 'utf8mb4'
|
||||
#
|
||||
# MDEV-10865 COLLATE keyword doesn't work in PREPARE query
|
||||
#
|
||||
SET NAMES utf8mb4;
|
||||
CREATE TABLE t1 (
|
||||
c1 varchar(500) COLLATE utf8mb4_unicode_ci NOT NULL
|
||||
) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
INSERT INTO t1 VALUES ('jj');
|
||||
SELECT * FROM t1 WHERE c1 LIKE 'jj' COLLATE utf8mb4_unicode_ci;
|
||||
c1
|
||||
jj
|
||||
PREPARE stmt FROM 'SELECT * FROM t1 WHERE c1 LIKE ? COLLATE utf8mb4_unicode_ci';
|
||||
EXECUTE stmt USING 'jj';
|
||||
c1
|
||||
jj
|
||||
DROP TABLE t1;
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE utf8mb4_unicode_ci AS c1';
|
||||
EXECUTE stmt USING 'test';
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT CONCAT(?) COLLATE utf8mb4_unicode_ci AS c1';
|
||||
EXECUTE stmt USING 'test';
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 AS SELECT NULL COLLATE utf8mb4_unicode_ci AS c1;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` char(0) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 AS SELECT CONCAT(NULL) COLLATE utf8mb4_unicode_ci AS c1;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` char(0) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 10.11 tests
|
||||
#
|
||||
|
@ -2068,25 +2068,6 @@ DROP TABLE t1;
|
||||
--echo # End of 10.2 tests
|
||||
--echo #
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Start of 10.5 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-24584 Selecting INT column with COLLATE utf8mb4_general_ci throws an error
|
||||
--echo #
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SELECT 1 COLLATE utf8mb4_general_ci;
|
||||
SELECT 1 COLLATE utf8mb4_bin;
|
||||
--error ER_COLLATION_CHARSET_MISMATCH
|
||||
SELECT 1 COLLATE latin1_swedish_ci;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.5 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # Start of 10.6 tests
|
||||
--echo #
|
||||
@ -2112,3 +2093,55 @@ DROP TABLE t1;
|
||||
--echo #
|
||||
--echo # End of 10.6 tests
|
||||
--echo #
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Start of 10.11 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-24584 Selecting INT column with COLLATE utf8mb4_general_ci throws an error
|
||||
--echo #
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SELECT 1 COLLATE utf8mb4_general_ci;
|
||||
SELECT 1 COLLATE utf8mb4_bin;
|
||||
--error ER_COLLATION_CHARSET_MISMATCH
|
||||
SELECT 1 COLLATE latin1_swedish_ci;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-10865 COLLATE keyword doesn't work in PREPARE query
|
||||
--echo #
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
CREATE TABLE t1 (
|
||||
c1 varchar(500) COLLATE utf8mb4_unicode_ci NOT NULL
|
||||
) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
INSERT INTO t1 VALUES ('jj');
|
||||
SELECT * FROM t1 WHERE c1 LIKE 'jj' COLLATE utf8mb4_unicode_ci;
|
||||
PREPARE stmt FROM 'SELECT * FROM t1 WHERE c1 LIKE ? COLLATE utf8mb4_unicode_ci';
|
||||
EXECUTE stmt USING 'jj';
|
||||
DROP TABLE t1;
|
||||
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE utf8mb4_unicode_ci AS c1';
|
||||
EXECUTE stmt USING 'test';
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT CONCAT(?) COLLATE utf8mb4_unicode_ci AS c1';
|
||||
EXECUTE stmt USING 'test';
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 AS SELECT NULL COLLATE utf8mb4_unicode_ci AS c1;
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 AS SELECT CONCAT(NULL) COLLATE utf8mb4_unicode_ci AS c1;
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.11 tests
|
||||
--echo #
|
||||
|
10
sql/item.cc
10
sql/item.cc
@ -4119,6 +4119,7 @@ Item_param::Item_param(THD *thd, const LEX_CSTRING *name_arg,
|
||||
*/
|
||||
set_maybe_null();
|
||||
with_flags= with_flags | item_with_t::PARAM;
|
||||
collation= DTCollation(&my_charset_bin, DERIVATION_IGNORABLE);
|
||||
}
|
||||
|
||||
|
||||
@ -4174,7 +4175,7 @@ void Item_param::sync_clones()
|
||||
}
|
||||
|
||||
|
||||
void Item_param::set_null()
|
||||
void Item_param::set_null(const DTCollation &c)
|
||||
{
|
||||
DBUG_ENTER("Item_param::set_null");
|
||||
/*
|
||||
@ -4189,6 +4190,7 @@ void Item_param::set_null()
|
||||
*/
|
||||
max_length= 0;
|
||||
decimals= 0;
|
||||
collation= c;
|
||||
state= NULL_VALUE;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@ -4447,7 +4449,7 @@ bool Item_param::set_from_item(THD *thd, Item *item)
|
||||
longlong val= item->val_int();
|
||||
if (item->null_value)
|
||||
{
|
||||
set_null();
|
||||
set_null(DTCollation_numeric());
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
else
|
||||
@ -4465,7 +4467,7 @@ bool Item_param::set_from_item(THD *thd, Item *item)
|
||||
DBUG_RETURN(set_value(thd, item, &tmp, h));
|
||||
}
|
||||
else
|
||||
set_null();
|
||||
set_null_string(item->collation);
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@ -5048,7 +5050,7 @@ Item_param::set_value(THD *thd, sp_rcontext *ctx, Item **it)
|
||||
if (arg->save_in_value(thd, &tmp) ||
|
||||
set_value(thd, arg, &tmp, arg->type_handler()))
|
||||
{
|
||||
set_null();
|
||||
set_null_string(arg->collation);
|
||||
return false;
|
||||
}
|
||||
/* It is wrapper => other set_* shoud set null_value */
|
||||
|
27
sql/item.h
27
sql/item.h
@ -4234,7 +4234,32 @@ public:
|
||||
|
||||
void set_default();
|
||||
void set_ignore();
|
||||
void set_null();
|
||||
void set_null(const DTCollation &c);
|
||||
void set_null_string(const DTCollation &c)
|
||||
{
|
||||
/*
|
||||
We need to distinguish explicit NULL (marked by DERIVATION_IGNORABLE)
|
||||
from other item types:
|
||||
|
||||
- These statements should give an error, because
|
||||
the character set of the bound parameter is not known:
|
||||
EXECUTE IMMEDIATE "SELECT ? COLLATE utf8mb4_bin" USING NULL;
|
||||
EXECUTE IMMEDIATE "SELECT ? COLLATE utf8mb4_bin" USING CONCAT(NULL);
|
||||
|
||||
- These statements should return a good result, because
|
||||
the character set of the bound parameter is known:
|
||||
EXECUTE IMMEDIATE "SELECT ? COLLATE utf8mb4_bin"
|
||||
USING CONVERT(NULL USING utf8mb4);
|
||||
EXECUTE IMMEDIATE "SELECT ? COLLATE utf8mb4_bin"
|
||||
USING CAST(NULL AS CHAR CHARACTER SET utf8mb4);
|
||||
*/
|
||||
set_null(DTCollation(c.collation, MY_MAX(c.derivation,
|
||||
DERIVATION_COERCIBLE)));
|
||||
}
|
||||
void set_null()
|
||||
{
|
||||
set_null(DTCollation(&my_charset_bin, DERIVATION_IGNORABLE));
|
||||
}
|
||||
void set_int(longlong i, uint32 max_length_arg);
|
||||
void set_double(double i);
|
||||
void set_decimal(const char *str, ulong length);
|
||||
|
@ -3880,21 +3880,43 @@ String *Item_func_set_collation::val_str(String *str)
|
||||
str=args[0]->val_str(str);
|
||||
if ((null_value=args[0]->null_value))
|
||||
return 0;
|
||||
/*
|
||||
Let SCS be the character set of the source - args[0].
|
||||
Let TCS be the character set of the target - i.e. the character set
|
||||
of the collation specified in the COLLATE clause.
|
||||
|
||||
It's OK to return SQL NULL if SCS is not equal to TCS.
|
||||
This is possible on the explicit NULL or expressions derived from
|
||||
the explicit NULL:
|
||||
SELECT NULL COLLATE utf8mb4_general_ci;
|
||||
SELECT COALESCE(NULL) COLLATE utf8mb4_general_ci;
|
||||
|
||||
But for a non-NULL result SCS and TCS must be compatible:
|
||||
1. Either SCS==TCS
|
||||
2. Or SCS can be can be reinterpeted to TCS.
|
||||
This scenario is possible when args[0] is numeric and TCS->mbmaxlen==1.
|
||||
|
||||
If SCS and TCS are not compatible here, then something went wrong during
|
||||
fix_fields(), e.g. an Item_func_conv_charset was not added two wrap args[0].
|
||||
*/
|
||||
DBUG_ASSERT(my_charset_same(args[0]->collation.collation,
|
||||
collation.collation) ||
|
||||
(args[0]->collation.repertoire == MY_REPERTOIRE_ASCII &&
|
||||
!(collation.collation->state & MY_CS_NONASCII)));
|
||||
str->set_charset(collation.collation);
|
||||
return str;
|
||||
}
|
||||
|
||||
bool Item_func_set_collation::fix_length_and_dec(THD *thd)
|
||||
{
|
||||
if (agg_arg_charsets_for_string_result(collation, args, 1))
|
||||
if (agg_arg_charsets_for_string_result(collation, args, 1) ||
|
||||
collation.merge_collation(m_set_collation,
|
||||
args[0]->collation.repertoire,
|
||||
with_param() &&
|
||||
thd->lex->is_ps_or_view_context_analysis()))
|
||||
return true;
|
||||
Lex_exact_charset_opt_extended_collate cl(collation.collation, true);
|
||||
if (cl.merge_collation_override(m_set_collation))
|
||||
return true;
|
||||
collation.set(cl.collation().charset_info(), DERIVATION_EXPLICIT,
|
||||
args[0]->collation.repertoire);
|
||||
ulonglong max_char_length= (ulonglong) args[0]->max_char_length();
|
||||
fix_char_length_ulonglong(max_char_length * collation.collation->mbmaxlen);
|
||||
fix_char_length_ulonglong(max_char_length);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -33,6 +33,88 @@ const DTCollation &DTCollation_numeric::singleton()
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DTCollation::merge_charset_and_collation(CHARSET_INFO *cs,
|
||||
const Lex_extended_collation_st &cl,
|
||||
my_repertoire_t repertoire)
|
||||
{
|
||||
Lex_exact_charset_opt_extended_collate cscl(cs, true);
|
||||
if (cscl.merge_collation_override(cl))
|
||||
return true;
|
||||
set(cscl.collation().charset_info(), DERIVATION_EXPLICIT, repertoire);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool DTCollation::merge_collation(const Lex_extended_collation_st &cl,
|
||||
my_repertoire_t repertoire,
|
||||
bool allow_ignorable_with_context_collation)
|
||||
{
|
||||
if (derivation != DERIVATION_IGNORABLE)
|
||||
{
|
||||
// A known character set + an extended collation
|
||||
return merge_charset_and_collation(collation, cl, repertoire);
|
||||
}
|
||||
|
||||
if (cl.type() == Lex_extended_collation::TYPE_EXACT)
|
||||
{
|
||||
/*
|
||||
An unknown character set + an exact collation.
|
||||
Just use this exact collation.
|
||||
Examples:
|
||||
- Expressions derived from an explicit NULL:
|
||||
SELECT NULL COLLATE utf8mb4_general_ci;
|
||||
SELECT CONCAT(NULL) COLLATE utf8mb4_general_ci;
|
||||
Any collation is applicable to an explicit NULL.
|
||||
|
||||
- Expressions with PS parameters (at PREPARE time, not bound yet)
|
||||
SELECT ? COLLATE utf8mb4_general_ci;
|
||||
SELECT CONCAT(?) COLLATE utf8mb4_general_ci;
|
||||
The collation will be checked for applicability to the
|
||||
character set of the actual bound parameter at the EXECUTE time.
|
||||
We're now in PREPARE: let's assume it will be applicable.
|
||||
*/
|
||||
set(cl.charset_info(), DERIVATION_EXPLICIT, repertoire);
|
||||
return false;
|
||||
}
|
||||
|
||||
// An unknown character set + a contextually typed collation
|
||||
if (allow_ignorable_with_context_collation)
|
||||
{
|
||||
/*
|
||||
Expressions with non-bound PS parameters, PREPARE time.
|
||||
SELECT ? COLLATE uca1400_ai_ci;
|
||||
SELECT CONCAT(?) COLLATE uca1400_ai_ci;
|
||||
There is a chance the character set of the actual bound parameter
|
||||
will be known at the EXECUTE time (unless an explicit NULL is bound).
|
||||
|
||||
For now let's use utf8mb4 to resolve collations like uca1400_ai_ci.
|
||||
The real character set of the actual bound parameter expression will be
|
||||
later used to resolve the collation again, during the EXECUTE time.
|
||||
*/
|
||||
return merge_charset_and_collation(&my_charset_utf8mb4_general_ci,
|
||||
cl, repertoire);
|
||||
}
|
||||
|
||||
/*
|
||||
Expressions with an unknown character set:
|
||||
- Either without PS parameters at all:
|
||||
SELECT NULL COLLATE uca1400_ai_ci;
|
||||
SELECT CONCAT(NULL) COLLATE uca1400_ai_ci;
|
||||
- Or with PS parameters bound to NULL at EXECUTE time:
|
||||
EXECUTE IMMEDIATE
|
||||
'SELECT ? COLLATE uca1400_ai_ci' USING NULL;
|
||||
EXECUTE IMMEDIATE
|
||||
'SELECT CONCAT(?) COLLATE uca1400_ai_ci' USING NULL;
|
||||
EXECUTE IMMEDIATE
|
||||
'SELECT ? COLLATE uca1400_ai_ci' USING CONCAT(NULL);
|
||||
*/
|
||||
my_error(ER_NOT_ALLOWED_IN_THIS_CONTEXT, MYF(0), "NULL");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Named_type_handler<Type_handler_row> type_handler_row("row");
|
||||
|
||||
Named_type_handler<Type_handler_null> type_handler_null("null");
|
||||
|
@ -3076,6 +3076,12 @@ public:
|
||||
bool aggregate(const DTCollation &dt, uint flags= 0);
|
||||
bool set(DTCollation &dt1, DTCollation &dt2, uint flags= 0)
|
||||
{ set(dt1); return aggregate(dt2, flags); }
|
||||
bool merge_charset_and_collation(CHARSET_INFO *cs,
|
||||
const Lex_extended_collation_st &cl,
|
||||
my_repertoire_t repertoire);
|
||||
bool merge_collation(const Lex_extended_collation_st &cl,
|
||||
my_repertoire_t repertoire,
|
||||
bool allow_ignorable_with_context_collation);
|
||||
const char *derivation_name() const
|
||||
{
|
||||
switch(derivation)
|
||||
|
Loading…
x
Reference in New Issue
Block a user