Details
-
Bug
-
Status: Open (View Workflow)
-
Major
-
Resolution: Unresolved
-
10.11, 11.4, 11.8, 12.3, 13.0, 13.1, 13.2
Description
--source include/have_partition.inc
|
--source include/have_innodb.inc
|
|
|
SET NAMES utf8mb4; |
|
|
# 'a', 'ä' and 'a' are equal in utf8mb4_unicode_nopad_ci |
CREATE TABLE t1 (a CHAR(10) COLLATE utf8mb4_unicode_nopad_ci, PRIMARY KEY (a)) ENGINE=InnoDB PARTITION BY KEY (a) PARTITIONS 8; |
INSERT IGNORE INTO t1 VALUES ('a'),('ä'),('a'); |
--let $c= query_get_value(SELECT COUNT(*) AS c FROM t1, c, 1)
|
if ($c != 1) |
{
|
--die The PRIMARY KEY holds $c values that are equal in utf8mb4_unicode_nopad_ci, where it must hold one |
}
|
|
|
CREATE TABLE t2 (a CHAR(10) COLLATE utf8mb4_unicode_nopad_ci) PARTITION BY KEY (a) PARTITIONS 8; |
INSERT INTO t2 VALUES ('a'),('ä'),('a'); |
--let $c= query_get_value(SELECT COUNT(*) AS c FROM t2 WHERE a='ä', c, 1)
|
if ($c != 3) |
{
|
--die The condition a='ä' finds $c of the 3 rows that are equal to 'ä' in utf8mb4_unicode_nopad_ci |
}
|
|
|
CREATE TABLE t3 (a CHAR(10) COLLATE utf8mb4_unicode_nopad_ci, UNIQUE (a) USING HASH); |
INSERT IGNORE INTO t3 VALUES ('a'),('ä'),('a'); |
--let $c= query_get_value(SELECT COUNT(*) AS c FROM t3, c, 1)
|
if ($c != 1) |
{
|
--die The UNIQUE USING HASH column holds $c values that are equal in utf8mb4_unicode_nopad_ci, where it must hold one |
}
|
DROP TABLE t1, t2, t3; |
Leads to:
|
CS 13.1.0 da18481158c81ca94689702073c3e04aad85a6a3 (Debug, Clang 22.1.8-20260622) Build 18/08/2026 |
mysqltest: At line 12: The PRIMARY KEY holds 3 values that are equal in utf8mb4_unicode_nopad_ci, where it must hold one
|
The PRIMARY KEY of t1 and the UNIQUE ... USING HASH of t3 accept three equal values. On t2, partitioning changes the query result. The t2 and t3 parts fail in the same way when run on their own. t3 has no partitioning. With VARCHAR, or with the PAD SPACE collation utf8mb4_unicode_ci, t1 and t3 hold one row. Optimized builds give the same result.
From the code it seems that CHAR uses Field::hash_not_null() in sql/field.cc, which hashes all pack_length() bytes, the space padding included. 'a', 'ä' and 'a' take 1, 2 and 3 bytes, so each one is stored with a different number of padding spaces. The NO PAD hash function does not skip trailing spaces, so the three equal values get three different hashes. PARTITION BY KEY and UNIQUE ... USING HASH both use this hash. Field_varstring::hash_not_null() hashes only the value itself.
Attachments
Issue Links
- relates to
-
MDEV-40671 Non-unique values can be inserted into column with unique hash key
-
- Open
-