Skip to content

Commit f6989d1

Browse files
committed
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.
1 parent c91ec6a commit f6989d1

11 files changed

+626
-49
lines changed

mysql-test/main/ctype_collate_context.result

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3716,3 +3716,103 @@ DROP PROCEDURE p;
37163716
#
37173717
# End of 10.9 tests
37183718
#
3719+
#
3720+
# Start of 10.11 tests
3721+
#
3722+
#
3723+
# MDEV-10865 COLLATE keyword doesn't work in PREPARE query
3724+
#
3725+
SET NAMES utf8mb4;
3726+
#
3727+
# A context collation and an explicit NULL
3728+
#
3729+
SELECT NULL COLLATE uca1400_ai_ci;
3730+
ERROR HY000: 'NULL' is not allowed in this context
3731+
SELECT CONCAT(NULL) COLLATE uca1400_ai_ci;
3732+
ERROR HY000: 'NULL' is not allowed in this context
3733+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT NULL COLLATE uca1400_ai_ci AS c1';
3734+
ERROR HY000: 'NULL' is not allowed in this context
3735+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT CONCAT(NULL) COLLATE uca1400_ai_ci AS c1';
3736+
ERROR HY000: 'NULL' is not allowed in this context
3737+
#
3738+
# A context collation and a parameter bound to NULL
3739+
#
3740+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
3741+
EXECUTE stmt USING NULL;
3742+
ERROR HY000: 'NULL' is not allowed in this context
3743+
EXECUTE stmt USING CONCAT(NULL);
3744+
ERROR HY000: 'NULL' is not allowed in this context
3745+
EXECUTE stmt USING NULL COLLATE uca1400_ai_ci;
3746+
ERROR HY000: 'NULL' is not allowed in this context
3747+
EXECUTE stmt USING CONCAT(NULL) COLLATE uca1400_ai_ci;
3748+
ERROR HY000: 'NULL' is not allowed in this context
3749+
#
3750+
# A context collation and CONVERT(NULL USING ...)
3751+
#
3752+
EXECUTE stmt USING CONVERT(NULL USING utf8mb4);
3753+
SHOW CREATE TABLE t1;
3754+
Table Create Table
3755+
t1 CREATE TABLE `t1` (
3756+
`c1` char(0) CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci DEFAULT NULL
3757+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
3758+
DROP TABLE t1;
3759+
EXECUTE stmt USING CONVERT(NULL USING utf8mb4) COLLATE uca1400_ai_ci;
3760+
SHOW CREATE TABLE t1;
3761+
Table Create Table
3762+
t1 CREATE TABLE `t1` (
3763+
`c1` char(0) CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci DEFAULT NULL
3764+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
3765+
DROP TABLE t1;
3766+
EXECUTE stmt USING CONVERT(NULL USING binary);
3767+
ERROR 42000: COLLATION 'uca1400_ai_ci' is not valid for CHARACTER SET 'binary'
3768+
EXECUTE stmt USING CONVERT(NULL USING latin1);
3769+
ERROR 42000: COLLATION 'uca1400_ai_ci' is not valid for CHARACTER SET 'latin1'
3770+
#
3771+
# A context collation and an expression with a parameter
3772+
# whose character does not get resolved when bound to a not-NULL value
3773+
#
3774+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT LEFT(NULL,?) COLLATE uca1400_ai_ci AS c1';
3775+
EXECUTE stmt USING NULL;
3776+
ERROR HY000: 'NULL' is not allowed in this context
3777+
#
3778+
# A context collation and an expression with a parameter
3779+
# whose character set gets resolved when bound to a not-NULL value
3780+
#
3781+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
3782+
EXECUTE stmt USING 1;
3783+
SHOW CREATE TABLE t1;
3784+
Table Create Table
3785+
t1 CREATE TABLE `t1` (
3786+
`c1` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci DEFAULT NULL
3787+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
3788+
DROP TABLE t1;
3789+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
3790+
EXECUTE stmt USING _binary'test';
3791+
ERROR 42000: COLLATION 'uca1400_ai_ci' is not valid for CHARACTER SET 'binary'
3792+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
3793+
EXECUTE stmt USING 'test';
3794+
SHOW CREATE TABLE t1;
3795+
Table Create Table
3796+
t1 CREATE TABLE `t1` (
3797+
`c1` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci DEFAULT NULL
3798+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
3799+
DROP TABLE t1;
3800+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
3801+
EXECUTE stmt USING 'test' COLLATE utf8mb4_bin;
3802+
SHOW CREATE TABLE t1;
3803+
Table Create Table
3804+
t1 CREATE TABLE `t1` (
3805+
`c1` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci DEFAULT NULL
3806+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
3807+
DROP TABLE t1;
3808+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
3809+
EXECUTE stmt USING _latin1'test' COLLATE latin1_bin;
3810+
SHOW CREATE TABLE t1;
3811+
Table Create Table
3812+
t1 CREATE TABLE `t1` (
3813+
`c1` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci DEFAULT NULL
3814+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
3815+
DROP TABLE t1;
3816+
#
3817+
# End of 10.11 tests
3818+
#

mysql-test/main/ctype_collate_context.test

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,3 +401,103 @@ DROP PROCEDURE p;
401401
--echo #
402402
--echo # End of 10.9 tests
403403
--echo #
404+
405+
--echo #
406+
--echo # Start of 10.11 tests
407+
--echo #
408+
409+
--echo #
410+
--echo # MDEV-10865 COLLATE keyword doesn't work in PREPARE query
411+
--echo #
412+
413+
SET NAMES utf8mb4;
414+
415+
--echo #
416+
--echo # A context collation and an explicit NULL
417+
--echo #
418+
419+
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
420+
SELECT NULL COLLATE uca1400_ai_ci;
421+
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
422+
SELECT CONCAT(NULL) COLLATE uca1400_ai_ci;
423+
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
424+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT NULL COLLATE uca1400_ai_ci AS c1';
425+
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
426+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT CONCAT(NULL) COLLATE uca1400_ai_ci AS c1';
427+
428+
429+
--echo #
430+
--echo # A context collation and a parameter bound to NULL
431+
--echo #
432+
433+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
434+
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
435+
EXECUTE stmt USING NULL;
436+
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
437+
EXECUTE stmt USING CONCAT(NULL);
438+
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
439+
EXECUTE stmt USING NULL COLLATE uca1400_ai_ci;
440+
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
441+
EXECUTE stmt USING CONCAT(NULL) COLLATE uca1400_ai_ci;
442+
443+
--echo #
444+
--echo # A context collation and CONVERT(NULL USING ...)
445+
--echo #
446+
447+
EXECUTE stmt USING CONVERT(NULL USING utf8mb4);
448+
SHOW CREATE TABLE t1;
449+
DROP TABLE t1;
450+
451+
EXECUTE stmt USING CONVERT(NULL USING utf8mb4) COLLATE uca1400_ai_ci;
452+
SHOW CREATE TABLE t1;
453+
DROP TABLE t1;
454+
455+
--error ER_COLLATION_CHARSET_MISMATCH
456+
EXECUTE stmt USING CONVERT(NULL USING binary);
457+
458+
--error ER_COLLATION_CHARSET_MISMATCH
459+
EXECUTE stmt USING CONVERT(NULL USING latin1);
460+
461+
--echo #
462+
--echo # A context collation and an expression with a parameter
463+
--echo # whose character does not get resolved when bound to a not-NULL value
464+
--echo #
465+
466+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT LEFT(NULL,?) COLLATE uca1400_ai_ci AS c1';
467+
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
468+
EXECUTE stmt USING NULL;
469+
470+
471+
--echo #
472+
--echo # A context collation and an expression with a parameter
473+
--echo # whose character set gets resolved when bound to a not-NULL value
474+
--echo #
475+
476+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
477+
EXECUTE stmt USING 1;
478+
SHOW CREATE TABLE t1;
479+
DROP TABLE t1;
480+
481+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
482+
--error ER_COLLATION_CHARSET_MISMATCH
483+
EXECUTE stmt USING _binary'test';
484+
485+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
486+
EXECUTE stmt USING 'test';
487+
SHOW CREATE TABLE t1;
488+
DROP TABLE t1;
489+
490+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
491+
EXECUTE stmt USING 'test' COLLATE utf8mb4_bin;
492+
SHOW CREATE TABLE t1;
493+
DROP TABLE t1;
494+
495+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE uca1400_ai_ci AS c1';
496+
EXECUTE stmt USING _latin1'test' COLLATE latin1_bin;
497+
SHOW CREATE TABLE t1;
498+
DROP TABLE t1;
499+
500+
501+
--echo #
502+
--echo # End of 10.11 tests
503+
--echo #

mysql-test/main/ctype_utf32.result

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3024,3 +3024,88 @@ HEX(DATE_FORMAT(TIME'11:22:33',@format))
30243024
#
30253025
# End of 10.4 tests
30263026
#
3027+
#
3028+
# Start of 10.11 tests
3029+
#
3030+
#
3031+
# MDEV-10865 COLLATE keyword doesn't work in PREPARE query
3032+
#
3033+
#
3034+
# The collation is not applicable to the PS parameter
3035+
#
3036+
SET NAMES utf8mb4;
3037+
CREATE TABLE t1 (
3038+
c1 varchar(500) COLLATE utf32_unicode_ci NOT NULL
3039+
);
3040+
INSERT INTO t1 VALUES ('jj');
3041+
PREPARE stmt FROM 'SELECT * FROM t1 WHERE c1 LIKE ? COLLATE utf32_unicode_ci';
3042+
EXECUTE stmt USING 'jj';
3043+
ERROR 42000: COLLATION 'utf32_unicode_ci' is not valid for CHARACTER SET 'utf8mb4'
3044+
DROP TABLE t1;
3045+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE utf32_unicode_ci AS c1';
3046+
EXECUTE stmt USING 'test';
3047+
ERROR 42000: COLLATION 'utf32_unicode_ci' is not valid for CHARACTER SET 'utf8mb4'
3048+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT CONCAT(?) COLLATE utf32_unicode_ci AS c1';
3049+
EXECUTE stmt USING 'test';
3050+
ERROR 42000: COLLATION 'utf32_unicode_ci' is not valid for CHARACTER SET 'utf8mb4'
3051+
CREATE TABLE t1 AS SELECT NULL COLLATE utf32_unicode_ci AS c1;
3052+
SHOW CREATE TABLE t1;
3053+
Table Create Table
3054+
t1 CREATE TABLE `t1` (
3055+
`c1` char(0) CHARACTER SET utf32 COLLATE utf32_unicode_ci DEFAULT NULL
3056+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
3057+
DROP TABLE t1;
3058+
CREATE TABLE t1 AS SELECT CONCAT(NULL) COLLATE utf32_unicode_ci AS c1;
3059+
SHOW CREATE TABLE t1;
3060+
Table Create Table
3061+
t1 CREATE TABLE `t1` (
3062+
`c1` char(0) CHARACTER SET utf32 COLLATE utf32_unicode_ci DEFAULT NULL
3063+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
3064+
DROP TABLE t1;
3065+
#
3066+
# The collation is applicable to the PS parameter
3067+
#
3068+
SET NAMES utf8mb4, collation_connection=utf32_general_ci;
3069+
CREATE TABLE t1 (
3070+
c1 varchar(500) COLLATE utf32_unicode_ci NOT NULL
3071+
);
3072+
INSERT INTO t1 VALUES ('jj');
3073+
PREPARE stmt FROM 'SELECT * FROM t1 WHERE c1 LIKE ? COLLATE utf32_unicode_ci';
3074+
EXECUTE stmt USING 'jj';
3075+
c1
3076+
jj
3077+
DROP TABLE t1;
3078+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE utf32_unicode_ci AS c1';
3079+
EXECUTE stmt USING 'test';
3080+
SHOW CREATE TABLE t1;
3081+
Table Create Table
3082+
t1 CREATE TABLE `t1` (
3083+
`c1` varchar(4) CHARACTER SET utf32 COLLATE utf32_unicode_ci DEFAULT NULL
3084+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
3085+
DROP TABLE t1;
3086+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT CONCAT(?) COLLATE utf32_unicode_ci AS c1';
3087+
EXECUTE stmt USING 'test';
3088+
SHOW CREATE TABLE t1;
3089+
Table Create Table
3090+
t1 CREATE TABLE `t1` (
3091+
`c1` varchar(4) CHARACTER SET utf32 COLLATE utf32_unicode_ci DEFAULT NULL
3092+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
3093+
DROP TABLE t1;
3094+
CREATE TABLE t1 AS SELECT NULL COLLATE utf32_unicode_ci AS c1;
3095+
SHOW CREATE TABLE t1;
3096+
Table Create Table
3097+
t1 CREATE TABLE `t1` (
3098+
`c1` char(0) CHARACTER SET utf32 COLLATE utf32_unicode_ci DEFAULT NULL
3099+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
3100+
DROP TABLE t1;
3101+
CREATE TABLE t1 AS SELECT CONCAT(NULL) COLLATE utf32_unicode_ci AS c1;
3102+
SHOW CREATE TABLE t1;
3103+
Table Create Table
3104+
t1 CREATE TABLE `t1` (
3105+
`c1` char(0) CHARACTER SET utf32 COLLATE utf32_unicode_ci DEFAULT NULL
3106+
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
3107+
DROP TABLE t1;
3108+
SET NAMES utf8mb4;
3109+
#
3110+
# End of 10.11 tests
3111+
#

mysql-test/main/ctype_utf32.test

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,4 +1167,80 @@ SELECT HEX(DATE_FORMAT(TIME'11:22:33',@format));
11671167
--echo # End of 10.4 tests
11681168
--echo #
11691169

1170+
--echo #
1171+
--echo # Start of 10.11 tests
1172+
--echo #
1173+
1174+
--echo #
1175+
--echo # MDEV-10865 COLLATE keyword doesn't work in PREPARE query
1176+
--echo #
1177+
1178+
--echo #
1179+
--echo # The collation is not applicable to the PS parameter
1180+
--echo #
1181+
1182+
SET NAMES utf8mb4;
1183+
CREATE TABLE t1 (
1184+
c1 varchar(500) COLLATE utf32_unicode_ci NOT NULL
1185+
);
1186+
INSERT INTO t1 VALUES ('jj');
1187+
PREPARE stmt FROM 'SELECT * FROM t1 WHERE c1 LIKE ? COLLATE utf32_unicode_ci';
1188+
--error ER_COLLATION_CHARSET_MISMATCH
1189+
EXECUTE stmt USING 'jj';
1190+
DROP TABLE t1;
1191+
1192+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE utf32_unicode_ci AS c1';
1193+
--error ER_COLLATION_CHARSET_MISMATCH
1194+
EXECUTE stmt USING 'test';
1195+
1196+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT CONCAT(?) COLLATE utf32_unicode_ci AS c1';
1197+
--error ER_COLLATION_CHARSET_MISMATCH
1198+
EXECUTE stmt USING 'test';
1199+
1200+
CREATE TABLE t1 AS SELECT NULL COLLATE utf32_unicode_ci AS c1;
1201+
SHOW CREATE TABLE t1;
1202+
DROP TABLE t1;
1203+
1204+
CREATE TABLE t1 AS SELECT CONCAT(NULL) COLLATE utf32_unicode_ci AS c1;
1205+
SHOW CREATE TABLE t1;
1206+
DROP TABLE t1;
1207+
1208+
1209+
--echo #
1210+
--echo # The collation is applicable to the PS parameter
1211+
--echo #
1212+
1213+
SET NAMES utf8mb4, collation_connection=utf32_general_ci;
1214+
CREATE TABLE t1 (
1215+
c1 varchar(500) COLLATE utf32_unicode_ci NOT NULL
1216+
);
1217+
INSERT INTO t1 VALUES ('jj');
1218+
PREPARE stmt FROM 'SELECT * FROM t1 WHERE c1 LIKE ? COLLATE utf32_unicode_ci';
1219+
EXECUTE stmt USING 'jj';
1220+
DROP TABLE t1;
1221+
1222+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ? COLLATE utf32_unicode_ci AS c1';
1223+
EXECUTE stmt USING 'test';
1224+
SHOW CREATE TABLE t1;
1225+
DROP TABLE t1;
1226+
1227+
PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT CONCAT(?) COLLATE utf32_unicode_ci AS c1';
1228+
EXECUTE stmt USING 'test';
1229+
SHOW CREATE TABLE t1;
1230+
DROP TABLE t1;
1231+
1232+
CREATE TABLE t1 AS SELECT NULL COLLATE utf32_unicode_ci AS c1;
1233+
SHOW CREATE TABLE t1;
1234+
DROP TABLE t1;
1235+
1236+
CREATE TABLE t1 AS SELECT CONCAT(NULL) COLLATE utf32_unicode_ci AS c1;
1237+
SHOW CREATE TABLE t1;
1238+
DROP TABLE t1;
1239+
1240+
SET NAMES utf8mb4;
1241+
1242+
--echo #
1243+
--echo # End of 10.11 tests
1244+
--echo #
1245+
11701246
--enable_service_connection

0 commit comments

Comments
 (0)