Doris-Breakwater commented on issue #69215: URL: https://github.com/apache/doris/issues/69215#issuecomment-6235711253
Breakwater-GitHub-Analysis-Slot: slot_b3c00c5020a2 The reported numerical discrepancy is independently reproducible. Suggested triage area: BE expression CAST / DECIMAL correctness, with the decimal-backed VARIANT path also affected by the shared conversion. ### Verified evidence I inspected current master at `f937d950d45313f20864d287df453e1b90f5c615`. A standalone C++ reproduction of the integer conversion, division, and direct `fast_float` parsing paths produced **5,273,258 mismatches / 20,000,000 values**, matching the generator in this issue. This was a numeric-only reproduction, not an execution of the SQL against a Doris cluster. Exact rational comparisons independently confirm the nearest results for both witnesses: | Source decimal | Existing arithmetic / intermediate-double result | Direct target-type parsing result | | --- | --- | --- | | `29201.024999999998` → DOUBLE | `0x1.c84419999999ap+14` | `0x1.c844199999999p+14` | | `-9000000000.000000009` → FLOAT | `-8999999488` | `-9000000512` | The DOUBLE results differ by one ULP. The exact unscaled integer `29201024999999998` first becomes `29201025000000000` in binary64, so the division operates on an already changed numerator. The [DECIMAL conversion code](https://github.com/apache/doris/blob/f937d950d45313f20864d287df453e1b90f5c615/be/src/exprs/function/cast/cast_to_basic_number_common.h#L330-L354) confirms this mechanism; its DECIMALV2 overload uses the same arithmetic pattern. A separate test is still needed to establish the DECIMALV2 runtime scope. For FLOAT, the exact input lies `0.000000009` below the midpoint `-9000000000` between the two binary32 candidates. Parsing to binary64 loses that distinction and produces the midpoint; narrowing then chooses the even candidate `-8999999488`. Thus the original decimal is **not itself a tie**. [StringParser currently parses into a local `double` and returns it as the requested type](https://github.com/apache/doris/blob/f937d950d45313f20864d287df453e1b90f5c615/be/src/util/string_parser.hpp#L776-L782). Consequently, the current STRING→FLOAT route is not a reliable correctly-rounded oracle or workaround for this case. The VARIANT V2 mechanism also checks out: [`append_decimal`](https://github.com/apache/doris/blob/f937d950d45313f20864d287df453e1b90f5c615/be/src/exprs/function/cast/variant_v2/cast_variant_to_scalar.cpp#L156-L166) groups values by scale into Decimal128 columns, and [group execution](https://github.com/apache/doris/blob/f937d950d45313f20864d287df453e1b90f5c615/be/src/exprs/function/cast/variant_v2/cast_variant_to_scalar.cpp#L357-L387) invokes the ordinary scalar cast. This supports the reported decimal-backed path; it does not establish identical behavior for every VARIANT representation. ### Suggested PR checks The proposed direct-to-target digit conversion addresses both demonstrated mechanisms. Keeping the division path for DOUBLE when the numerator is exact and scale ≤22 is justified under round-to-nearest: those powers of ten are exactly representable in binary64, leaving only the final division rounding. The proposed strict `< 2^53` numerator bound is conservative; `2^53` itself is also exactly representable. Above scale 22 the denominator can also round, independently of numerator size. Please cover: - Both witnesses and their positive/negative counterparts, numerator boundaries around `2^53`, and scales 22/23. Include a denominator-rounding case with a small numerator. - Direct target-type expectations rather than the existing two-rounding formula in [`cast_to_float_double`](https://github.com/apache/doris/blob/f937d950d45313f20864d287df453e1b90f5c615/be/test/exprs/function/cast/cast_to_float_double.cpp#L974-L1015). Pin witness bits or exact expected values independently of the production conversion helper. - Relevant DECIMAL32/64/128/256 paths and an explicit decision on the DECIMALV2 overload; runtime columns, constant folding, nullable inputs, and strict/non-strict modes. Preserve the intended overflow-to-infinity behavior for large DECIMAL256→FLOAT values. - A decimal-backed VARIANT regression. If the change is limited to DECIMAL casts, document that STRING→FLOAT still has its separate intermediate-double issue. ### Remaining information and next step Please attach the exact FE/BE build commit(s) and link the forthcoming PR. For the VARIANT coverage, a small synthetic DDL/INSERT/SELECT reproducer showing how the element becomes decimal-backed would be sufficient; production data is unnecessary. The arithmetic evidence is sufficient to review the conversion fix without additional logs or a query profile. End-to-end Doris behavior, the reported fixed-run result, and the 40–60 ns/value cost have not been independently verified here. Next step: review the PR with the boundary and independent-oracle tests above, then run the supplied SQL on the exact affected build and patched build before deciding release/backport scope. For the demonstrated DOUBLE discrepancy, parsing the decimal's text directly to DOUBLE avoids the numerator/divisor rounding and provides a temporary workaround; it should not be generalized to FLOAT. -- 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]
