Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-41855

Partitioning by KEY ALGORITHM=XXH32 or XXH3 changes the query result: c = '' misses rows with a binary collation, also in tables created with 12.3

    XMLWordPrintable

Details

    Description

      --source include/have_partition.inc
       
      CREATE TABLE t1 (c VARCHAR(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin) PARTITION BY KEY ALGORITHM=XXH32 (c) PARTITIONS 7;
      INSERT INTO t1 VALUES (''),(' ');
      --let $n= `SELECT COUNT(*) FROM t1 WHERE c = ''`
      if ($n != 2)
      {
        --die KEY ALGORITHM=XXH32 on a utf8mb4_bin column: c = '' finds $n of the 2 rows
      }
       
      CREATE TABLE t2 (c VARCHAR(10) CHARACTER SET latin1 COLLATE latin1_bin) PARTITION BY KEY ALGORITHM=XXH3 (c) PARTITIONS 7;
      INSERT INTO t2 VALUES (''),(' ');
      --let $n= `SELECT COUNT(*) FROM t2 WHERE c = ''`
      if ($n != 2)
      {
        --die KEY ALGORITHM=XXH3 on a latin1_bin column: c = '' finds $n of the 2 rows
      }
      DROP TABLE t1, t2;

      Leads to:

      CS 13.1.2 87e62ca17270e163a6d41b3fc8d6f4d440f1bb88 (Optimized, Clang 22.1.8-20260622) Build 06/10/2026

      mysqltest: At line 8: KEY ALGORITHM=XXH32 on a utf8mb4_bin column: c = '' finds 1 of the 2 rows

      '' and ' ' are equal in these collations, but they are stored in different partitions. So c = '' and c = ' ' each find one row, and a PRIMARY KEY (c) accepts both values. Run alone, the XXH3 check on t2 fails the same way. Every PAD SPACE binary collation except utf32_bin gives the same result, with both algorithms. Debug builds give the same result. CS 12.3.4 and 13.0.2 find both rows. Without partitioning, XXH32(_utf8mb4 '' COLLATE utf8mb4_bin) is 0, and XXH32(_utf8mb4 ' ' COLLATE utf8mb4_bin) is 46947589.

      A table created with 12.3 is also affected. On CS 12.3.4, this SQL gives 2 and 1:

      CREATE TABLE t1 (c VARCHAR(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin) PARTITION BY KEY ALGORITHM=XXH32 (c) PARTITIONS 7;
      INSERT INTO t1 VALUES (''),(' ');
      CREATE TABLE t2 (c VARBINARY(10)) PARTITION BY KEY ALGORITHM=XXH3 (c) PARTITIONS 7;
      INSERT INTO t2 VALUES ('');
      SELECT (SELECT COUNT(*) FROM t1 WHERE c = '') AS t1, (SELECT COUNT(*) FROM t2 WHERE c = '') AS t2;

      With the same data directory, CS 13.1.2 gives:

      CS 13.1.2 87e62ca17270e163a6d41b3fc8d6f4d440f1bb88 (Debug, Clang 22.1.8-20260622) Build 06/10/2026

      --------------
      SELECT (SELECT COUNT(*) FROM t1 WHERE c = '') AS t1, (SELECT COUNT(*) FROM t2 WHERE c = '') AS t2
      --------------
       
      +------+------+
      | t1   | t2   |
      +------+------+
      |    0 |    0 |
      +------+------+

      CHECK TABLE t1, t2 reports "Found a misplaced row" for both tables. mariadb-upgrade reports both tables as OK, and the SELECT still gives 0 and 0.

      From the code it seems that Hasher::add() in sql/sql_type.h does not hash a value of length 0, so '' leaves the hash at its start value 0. For ' ', the collation removes the trailing space and hashes the remaining 0 bytes, and XXH32 of 0 bytes is 0x02CC5D05, not 0. In 12.3 and 13.0, Hasher::add() also hashes a value of length 0, so '' hashes as ' ' does.

      Attachments

        Issue Links

          Activity

            People

              danblack Daniel Black
              Roel Roel Van de Paar
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.