mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-39530 Collation mix issue after update
A user variable assignment (e.g. @p:=expr) exposed collation derivation
DERIVATION_COERCIBLE, the same level as a string literal. MDEV-35041
introduced DERIVATION_USERVAR (weaker than a literal) and applied it when
reading a user variable back via Item_func_get_user_var, but not to the
inline assignment form handled by Item_func_set_user_var.
As a result, an assignment carrying a column collation and a string literal
carrying the (possibly different) connection collation ended up at the same
derivation level with different collations, raising a spurious
"Illegal mix of collations" error, e.g.:
SET NAMES utf8mb3 COLLATE utf8mb3_uca1400_ai_ci;
SELECT IF((@p:=(SELECT f.Path FROM file f WHERE f.ID=1
AND f.Path REGEXP "^xx"))!="",1,2);
Make Item_func_set_user_var use DERIVATION_USERVAR so that assigning a user
variable has the same derivation as reading it back, keeping it weaker than
a literal. The query above now works again as it did before MDEV-35041.
All new code of the whole pull request, including one or several files
that are either new files or modified ones, are contributed under the
BSD-new license. I am contributing on behalf of my employer Amazon Web
Services, Inc.
This commit is contained in:
committed by
Raghunandan Bhat
parent
1632ce83e6
commit
f897dc5ca1
@@ -808,3 +808,25 @@ ts
|
||||
2024-01-26 21:38:02
|
||||
drop table t1;
|
||||
# End of 10.6 tests
|
||||
#
|
||||
# MDEV-39530: Collation mix issue after update
|
||||
#
|
||||
# Reproduce the environment from the report: character_set_collations
|
||||
# maps utf8mb3 to utf8mb3_uca1400_ai_ci and the connection uses that
|
||||
# collation.
|
||||
SET NAMES utf8mb3 COLLATE utf8mb3_uca1400_ai_ci;
|
||||
SELECT @@character_set_collations, @@collation_connection;
|
||||
@@character_set_collations @@collation_connection
|
||||
utf8mb3=utf8mb3_uca1400_ai_ci,ucs2=ucs2_uca1400_ai_ci,utf8mb4=utf8mb4_uca1400_ai_ci,utf16=utf16_uca1400_ai_ci,utf32=utf32_uca1400_ai_ci utf8mb3_uca1400_ai_ci
|
||||
CREATE TABLE file (
|
||||
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`Path` varchar(800) NOT NULL DEFAULT ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
INSERT INTO file VALUES (1,"text");
|
||||
# This query used to work in 11.4 but raises
|
||||
# ER_CANT_AGGREGATE_2COLLATIONS in 12.1+
|
||||
SELECT IF((@p:=(SELECT f.Path FROM file f WHERE f.ID=1 AND f.Path REGEXP "^xx"))!="",1,2);
|
||||
IF((@p:=(SELECT f.Path FROM file f WHERE f.ID=1 AND f.Path REGEXP "^xx"))!="",1,2)
|
||||
2
|
||||
DROP TABLE file;
|
||||
# End of 12.3 tests
|
||||
|
||||
@@ -378,3 +378,28 @@ select * from t1 order by ts collate utf8_bin;
|
||||
drop table t1;
|
||||
|
||||
--echo # End of 10.6 tests
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39530: Collation mix issue after update
|
||||
--echo #
|
||||
|
||||
--echo # Reproduce the environment from the report: character_set_collations
|
||||
--echo # maps utf8mb3 to utf8mb3_uca1400_ai_ci and the connection uses that
|
||||
--echo # collation.
|
||||
SET NAMES utf8mb3 COLLATE utf8mb3_uca1400_ai_ci;
|
||||
SELECT @@character_set_collations, @@collation_connection;
|
||||
|
||||
CREATE TABLE file (
|
||||
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`Path` varchar(800) NOT NULL DEFAULT ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
INSERT INTO file VALUES (1,"text");
|
||||
|
||||
--echo # This query used to work in 11.4 but raises
|
||||
--echo # ER_CANT_AGGREGATE_2COLLATIONS in 12.1+
|
||||
SELECT IF((@p:=(SELECT f.Path FROM file f WHERE f.ID=1 AND f.Path REGEXP "^xx"))!="",1,2);
|
||||
|
||||
DROP TABLE file;
|
||||
|
||||
--echo # End of 12.3 tests
|
||||
|
||||
@@ -162,13 +162,13 @@ collation(@a:=_latin2'test')
|
||||
latin2_general_ci
|
||||
select coercibility(@a:=_latin2'test');
|
||||
coercibility(@a:=_latin2'test')
|
||||
6
|
||||
5
|
||||
select collation(@a:=_latin2'test' collate latin2_bin);
|
||||
collation(@a:=_latin2'test' collate latin2_bin)
|
||||
latin2_bin
|
||||
select coercibility(@a:=_latin2'test' collate latin2_bin);
|
||||
coercibility(@a:=_latin2'test' collate latin2_bin)
|
||||
6
|
||||
5
|
||||
select (@a:=_latin2'test' collate latin2_bin) = _latin2'TEST';
|
||||
(@a:=_latin2'test' collate latin2_bin) = _latin2'TEST'
|
||||
0
|
||||
|
||||
@@ -4849,9 +4849,17 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
|
||||
if (!m_var_entry->charset() || !null_item)
|
||||
m_var_entry->set_charset(args[0]->collation.derivation == DERIVATION_NUMERIC ?
|
||||
&my_charset_numeric : args[0]->collation.collation);
|
||||
/*
|
||||
A user variable assignment (e.g. @p:=expr) must expose the same collation
|
||||
derivation as reading the variable back with Item_func_get_user_var, which
|
||||
uses DERIVATION_USERVAR (see MDEV-35041). Using DERIVATION_COERCIBLE here
|
||||
made the assignment as strong as a string literal, causing "Illegal mix of
|
||||
collations" conflicts against literals that carry the (possibly different)
|
||||
connection collation (MDEV-39530).
|
||||
*/
|
||||
collation.set(m_var_entry->charset(),
|
||||
args[0]->collation.derivation == DERIVATION_NUMERIC ?
|
||||
DERIVATION_NUMERIC : DERIVATION_COERCIBLE);
|
||||
DERIVATION_NUMERIC : DERIVATION_USERVAR);
|
||||
switch (args[0]->result_type()) {
|
||||
case STRING_RESULT:
|
||||
case TIME_RESULT:
|
||||
|
||||
Reference in New Issue
Block a user