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

Partitioning changes the query result: a range on a nullable column misses the rows in the DEFAULT partition of a LIST table

    XMLWordPrintable

Details

    Description

      --source include/have_partition.inc
       
      CREATE TABLE t1 (c TINYINT) PARTITION BY LIST (c) (PARTITION p0 VALUES IN (1,2), PARTITION pdef DEFAULT);
      INSERT INTO t1 VALUES (1),(3),(4);
      --let $n= query_get_value(SELECT COUNT(*) AS n FROM t1 WHERE c BETWEEN 1 AND 4, n, 1)
      if ($n != 3)
      {
        --die A range on a nullable TINYINT column misses the rows in the DEFAULT partition: the DEFAULT partition is pruned
      }
      DROP TABLE t1;
       
      CREATE TABLE t1 (c SMALLINT) PARTITION BY LIST (c) (PARTITION p0 VALUES IN (1,2), PARTITION pdef DEFAULT);
      INSERT INTO t1 VALUES (1),(3),(257);
      --let $n= query_get_value(SELECT COUNT(*) AS n FROM t1 WHERE c BETWEEN 1 AND 257, n, 1)
      if ($n != 3)
      {
        --die A range on a nullable SMALLINT column with bounds 1 and 257 misses the rows in the DEFAULT partition
      }
      DROP TABLE t1;

      Leads to:

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

      mysqltest: At line 8: A range on a nullable TINYINT column misses the rows in the DEFAULT partition: the DEFAULT partition is pruned

      Partitioning changes the query result. Without partitioning, or with a NOT NULL column, the count is 3. EXPLAIN PARTITIONS shows p0 only. A range whose two bounds differ only in the highest byte of the value is pruned like an equality. For a TINYINT column, that is every BETWEEN. For the SMALLINT table, BETWEEN 1 AND 257 misses the rows in pdef, BETWEEN 1 AND 258 finds them, and BETWEEN 2 AND 258 returns no row. A nullable YEAR column, also one byte, gives the same. InnoDB, Aria and debug builds give the same result.

      From the code it seems that in get_part_iter_for_interval_via_mapping() (sql/sql_partition.cc), the memcmp(min_value, max_value, field_len) that sets can_match_multiple_values starts at the NULL indicator byte of a nullable field, so it does not compare the last byte of the value. With can_match_multiple_values false, ret_default_part is not set.

      Attachments

        Activity

          People

            ycp Yuchen Pei
            Roel Roel Van de Paar
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:

              Time Tracking

                Estimated:
                Original Estimate - Not Specified
                Not Specified
                Remaining:
                Remaining Estimate - Not Specified
                Not Specified
                Logged:
                Time Spent - 35m
                35m

                Git Integration

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