Details
-
Bug
-
Status: Confirmed (View Workflow)
-
Major
-
Resolution: Unresolved
-
10.11, 11.4, 11.8, 12.3, 12.3.2
Description
Summary
Wrong result: FIND_IN_SET returns 0 when needle is longer in bytes than haystack token but equal under collation
Description
Under utf8mb4 accent-insensitive collations (e.g. utf8mb4_unicode_ci, utf8mb4_uca1400_ai_ci, utf8mb4_general_ci), 'ắ' = 'a' is true, but:
FIND_IN_SET('ắ', 'a') -- returns 0 (wrong; expect 1) |
Root cause in Item_func_find_in_set::val_int() (sql/item_func.cc):
if ((int) (buffer->length() - find->length()) >= 0) |
{
|
// ... strnncoll per comma-separated token ... |
}
|
return 0; |
If the entire list string is shorter in bytes than the needle, the function returns 0 without calling strnncoll. That is incorrect when the collation equates a multi-byte character to a shorter string.
FIND_IN_SET('ắ', 'a,b') -- returns 1 (correct) |
How to repeat
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; |
|
|
SELECT 'ắ' = 'a' AS eq; -- 1 |
SELECT FIND_IN_SET('ắ', 'a') AS fis1; -- Actual: 0; Expected: 1 |
SELECT FIND_IN_SET('ắ', 'a,b,c') AS fis2; -- Actual: 1; Expected: 1 |
SELECT FIND_IN_SET('a', 'ắ') AS fis3; -- Actual: 1; Expected: 1 |
|
|
-- Also wrong on utf8mb4_general_ci / utf8mb4_uca1400_ai_ci with the same shape
|
SET NAMES utf8mb4 COLLATE utf8mb4_general_ci; |
SELECT 'ắ' = 'a', FIND_IN_SET('ắ', 'a'); -- 1, 0 |
Observed on: 12.3.2-MariaDB
Actual result
FIND_IN_SET('ắ', 'a') = 0 while 'ắ' = 'a' is true.
Expected result
FIND_IN_SET('ắ', 'a') = 1 (needle equals the sole list element under the connection collation).
Attachments
Issue Links
- relates to
-
MDEV-40866 LOCATE/INSTR return 0 for strings that compare equal under utf8mb4_*_ci (e.g. ắ vs a)
-
- Confirmed
-