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]

Reply via email to