1
0
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:
Geng Tian
2026-07-15 17:08:45 +00:00
committed by Raghunandan Bhat
parent 1632ce83e6
commit f897dc5ca1
4 changed files with 58 additions and 3 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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: