Skip to content

MDEV-39194 SUM(b'1100') and SUM(DISTINCT b'1100') return different numeric results for the same BIT literal (e.g. 12 vs 9) - #5717

Open
DerZc wants to merge 1 commit into
MariaDB:11.4from
DerZc:fix-mdev-39194
Open

DerZc wants to merge 1 commit into
MariaDB:11.4from
DerZc:fix-mdev-39194

Conversation

@DerZc

@DerZc DerZc commented Sep 21, 2026 •

Copy link
Copy Markdown

SUM(DISTINCT b'1100') returns 9 instead of 12. Bit and hybrid hex literals inherit the default numeric DISTINCT temporary field, which uses their byte length as a DOUBLE(M,0) display width and clips the stored value.

Bug report: https://jira.mariadb.org/browse/MDEV-39194

Changes

  • Override Type_handler_hex_hybrid::make_num_distinct_aggregator_field to use unsigned integer storage for numeric DISTINCT aggregation of bit and hybrid hex literals.
  • Preserve argument-based field selection for other types. In particular, decimal DISTINCT inputs retain their original scale: AVG(DISTINCT b / a) in main.distinct_notembedded continues to return 0.61110000.
  • Extend the existing main.sum_distinct regression with zero, byte boundaries, hybrid hex literals, the unsigned 64-bit boundary, duplicate inputs, AVG, COUNT, and the decimal precision control.

Validation

Built against 11.4 at d10e5d726799b1cd57cc866f40aad68c720803da with GCC 13 in Release mode.

  • The expanded main.sum_distinct regression fails on the unchanged base and passes with this fix.
  • Reproduced the previous PR's main.distinct_notembedded failure locally: 0.61111111 instead of 0.61110000. This matches all eight failed Buildbot configurations and AppVeyor; the corrected implementation passes without changing that test's expected output.
  • All 11 selected MTR tests passed: main.sum_distinct, main.distinct_notembedded, main.distinct, main.func_group, main.group_by, main.select, main.type_bit, main.type_bit_innodb, main.type_decimal, main.type_float, and main.type_hex_hybrid.
  • main.sum_distinct and main.distinct_notembedded also passed with --ps-protocol and with --view-protocol, for 15 successful test executions overall.
  • No test-state cleanup failures in these local runs. git diff --check passed.

The full regression suite and Windows builds were not run locally.

@CLAassistant

CLAassistant commented Sep 21, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@gkodinov gkodinov added the External Contribution All PRs from entities outside of MariaDB Foundation, Corporation, Codership agreements. label Sep 23, 2026
@gkodinov gkodinov self-assigned this Sep 23, 2026

@gkodinov gkodinov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contribution! This is a preliminary review.

To get to the final review:

  • squash the two commits into one
  • make sure there's no failing tests in the build bot runs.

SUM(DISTINCT b'1100') returns 9 instead of 12 because the hybrid
hex/bit literal handler inherits the default DOUBLE temporary field.
The literal's byte length becomes the DOUBLE(M,0) display width,
which clips the numeric value when it is stored.

Override make_num_distinct_aggregator_field for Type_handler_hex_hybrid
to use an unsigned integer temporary field. Keep argument-based field
selection for other types so DISTINCT retains the input expression's
precision and scale, including for AVG of decimal expressions.

Extend main.sum_distinct with bit and hex literals, byte boundaries,
the unsigned 64-bit boundary, duplicate inputs, AVG, COUNT, and a
decimal AVG control. Keep existing decimal result expectations intact.

Bug report: https://jira.mariadb.org/browse/MDEV-39194

@gkodinov gkodinov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! LGTM. Please stand by for the final review.

@raghunandanbhat raghunandanbhat left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @DerZc for the fix. comments inline.
Please re-write commit message in this format-

MDEV-xxxx: <Titile>

Problem: < Short description of the issue >

Fix: <Short description of your fix>

Comment thread sql/sql_type.cc
Hex and bit literals have unsigned integer values in numeric aggregates.
Their max_length is a byte count, not a DOUBLE(M,0) display width.
*/
return type_handler_ulonglong.make_num_distinct_aggregator_field(mem_root,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't use the hard-coded type_handler_ulonglong here.
Any specific reason why we can't just return a new Field_longlong() from this function? (making sure it is always unsigned, ofc). for ex:

Field *
Type_handler_hex_hybrid::make_num_distinct_aggregator_field(
    MEM_ROOT *mem_root, const Item *item) const
{
  /*
    Hex and bit literals have unsigned integer values in numeric aggregates.
    Their max_length is a byte count, not a DOUBLE(M,0) display width.
  */
  return new (mem_root)
          Field_longlong(NULL, item->max_length,
                         (uchar *) (item->maybe_null() ? "" : 0),
                         item->maybe_null() ? 1 : 0, Field::NONE,
                         &item->name, 0, true /* unsigned */);
}

COUNT(DISTINCT b'1100') AS bit_count FROM t1;
# DISTINCT inputs keep the argument's decimal scale, not AVG's result scale.
SELECT AVG(DISTINCT b / a) AS decimal_average FROM t1;
DROP TABLE t1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add end of test marker here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

External Contribution All PRs from entities outside of MariaDB Foundation, Corporation, Codership agreements.

Development

Successfully merging this pull request may close these issues.

4 participants