Doris-Breakwater commented on issue #68222: URL: https://github.com/apache/doris/issues/68222#issuecomment-5742369623
Breakwater-GitHub-Analysis-Slot: slot_5b7a1add75c6 ### Initial assessment This is a confirmed deterministic correctness bug in the BE `width_bucket` implementation at commit `979e053f0802fbc48f83dafe7f713c02968415a8`. The issue is currently open with no labels; the supplied commit and scalar SQL are sufficient for initial triage. **Verified root cause** In [`FunctionWidthBucket::_execute`](https://github.com/apache/doris/blob/979e053f0802fbc48f83dafe7f713c02968415a8/be/src/exprs/function/function_width_bucket.cpp#L109-L122), `average_value` is correctly computed with floating-point arithmetic: ```cpp auto average_value = (max_value - min_value) / (1.0 * num_buckets); ``` However, the in-range branch then checks the width again using the input type's arithmetic: ```cpp if ((max_value - min_value) / num_buckets == 0) { continue; } ``` For the integral overloads, this is integer division. For example, `10 / 20` and `2 / 5` truncate to `0`; `continue` leaves the pre-zeroed result unchanged. That directly explains every reported result, including `width_bucket(0, 0, 10, 20)`: an expression equal to the lower bound reaches the stale guard and incorrectly remains bucket `0` instead of bucket `1`. The confirmed scope is the `TINYINT`, `SMALLINT`, `INT`, and `BIGINT` execution paths when `0 < max_value - min_value < num_buckets` and the expression is in `[min_value, max_value)`. Values below `min_value` and values at/above `max_value` take earlier branches and are not affected by this guard. The same integer-truncation mechanism does not apply to the floating-point overloads. History supports this diagnosis: the guard protected the original integer denominator. [PR #24673](https://github.com/apache/doris/pull/24673) changed the actual bucket calculation to divide by the floating-point `average_value`, but retained the old integer zero check. Existing regression coverage also misses this shape: the direct integer case uses a span of 11 with 10 buckets, while the generated integral cases use a span of 1 with 1 bucket. **Missing information** No additional logs, profile, or environment details are required to establish this issue. The version, exact commit, deterministic reproduction, and expected values are all present. I did not run a Doris cluster or a candidate patch during this triage; the conclusion is based on the reported runtime output and inspection of the exact commit. **Recommended next steps** 1. In the reporter's proposed PR, remove the stale integral-division guard or make any zero-width validation use the same non-truncating calculation as `average_value`. Keep the existing below-range (`0`) and at/above-range (`num_buckets + 1`) behavior unchanged. 2. Add the four reported constant queries as regression cases in `test_width_bucket_function.groovy`, including the lower-bound case. 3. Add explicit-cast coverage for all four integral overloads, plus `expr = min_value`, an in-range value near `max_value`, and the existing out-of-range boundaries. This prevents the fix from only covering the literal type selected by the analyzer. 4. Run the focused `test_width_bucket_function` regression suite and the existing Nereids scalar-function coverage before merge. The fix direction above is code-derived but has not yet been implemented or test-validated here. Equal or descending bounds are outside the reported failure and should not have their semantics changed incidentally. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
