Visitar URL original
[Bug] DOUBLE to LARGEINT cast folded by FE uses the decimal string, BE converts the binary value · Issue #68722 · apache/doris · GitHub
Skip to content

[Bug] DOUBLE to LARGEINT cast folded by FE uses the decimal string, BE converts the binary value #68722

Description

@r33s3n6

Search before asking

  • I had searched in the issues and found no similar issues.

Version

4.1.4 (doris-4.1.4-rc04-ad35a140c7f), single FE + single BE

What's Wrong?

CAST(CAST(1e38 AS DOUBLE) AS LARGEINT) folds to 100000000000000000000000000000000000000 in FE and is 99999999999999997748809823456034029568 (the exact value of the double) in BE.

FE folding: 100000000000000000000000000000000000000. BE: 99999999999999997748809823456034029568.

SET enable_sql_cache = false

SELECT CAST(CAST(1e38 AS DOUBLE) AS LARGEINT) AS fe, CAST(d1 AS LARGEINT) AS be FROM t

+-----------------------------------------+----------------------------------------+
| fe                                      | be                                     |
+-----------------------------------------+----------------------------------------+
| 100000000000000000000000000000000000000 | 99999999999999997748809823456034029568 |
+-----------------------------------------+----------------------------------------+

SET debug_skip_fold_constant = true

SELECT CAST(CAST(1e38 AS DOUBLE) AS LARGEINT)

+----------------------------------------+
| CAST(CAST(1e38 AS DOUBLE) AS LARGEINT) |
+----------------------------------------+
| 99999999999999997748809823456034029568 |
+----------------------------------------+
  • FE constant folding: all arguments are literals, so Nereids folds the call during planning. Check: EXPLAIN shows the literal in place of the call: final projections: 100000000000000000000000000000000000000, CAST(d1[#1] AS largeint)
  • BE execution: the arguments are columns (or SET debug_skip_fold_constant = true), so BE computes the call. Check: EXPLAIN keeps the call.

What You Expected?

FE folding and BE give the same value.

How to Reproduce?

Deployment: single FE + single BE, default session variables.

CREATE TABLE t(id INT, d1 DOUBLE)
  DISTRIBUTED BY HASH(id) BUCKETS 1 PROPERTIES('replication_num' = '1');
INSERT INTO t VALUES (1, 1e38);

SET enable_sql_cache = false;
SELECT CAST(CAST(1e38 AS DOUBLE) AS LARGEINT) AS fe, CAST(d1 AS LARGEINT) AS be FROM t;
SET debug_skip_fold_constant = true;
SELECT CAST(CAST(1e38 AS DOUBLE) AS LARGEINT);

Anything Else?

FE's FractionalLiteral builds new BigDecimal(value.toString()) from the shortest decimal string; BE truncates the binary value.

Found with AI assistance.

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Code of Conduct

Activity

  1. Doris-Breakwater commented on Oct 4, 2026

    @Doris-Breakwater
    Collaborator

    Breakwater-GitHub-Analysis-Slot: slot_35f81dc4b4d8

    Triage: This is a credible FE/BE correctness inconsistency for DOUBLE to LARGEINT constant folding in the reported 4.1.4 build. The issue is open and has no labels. The supplied SQL, version, and EXPLAIN observations are sufficient for a targeted regression case; no profile or additional logs are needed to identify this conversion mismatch. I reviewed the exact reported commit (ad35a140c7f) read-only, but did not run the SQL against a Doris cluster.

    Verified in source: Nereids' FE fold calls checkedCastTo for a literal cast (fold visitor). For a DoubleLiteral, the integral cast path constructs BigDecimal from value.toString(), truncates it, and builds a LargeIntLiteral (FE cast). Double.toString(1e38) is 1.0E38, so this path yields 100000000000000000000000000000000000000. The BE DOUBLE to integer path calls CastToInt::from_float (dispatch); that routine checks range, truncates the floating value, then casts the binary value to the destination integer (conversion). The exact binary64 value of 1e38 is the reported 99999999999999997748809823456034029568. A local Java numeric check produced both values from new BigDecimal(Double.toString(d)) and new BigDecimal(d), respectively. This accounts for the reported FE/BE difference; it does not establish whether any other cast types are affected.

    Suggested next steps: Add a paired constant-versus-column regression for this expression on the 4.1 branch, including EXPLAIN, plus negative values and values close to the LARGEINT bounds to check truncation and overflow behavior. Then align the FE fold with the BE conversion semantics while preserving strict/non-strict overflow behavior, and run the existing DOUBLE to LARGEINT cast suite. The existing suite covers column casts (regression suite); this case needs an explicit fold-versus-execution assertion. For an immediate session-level mitigation, the reporter's debug_skip_fold_constant = true makes this expression execute on BE, but it disables constant folding more broadly and is best limited to affected queries pending a fix.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions