hanke580 opened a new issue, #68714:
URL: https://github.com/apache/doris/issues/68714

   ### Search before asking
   
   - [x] I had searched in the 
[issues](https://github.com/apache/doris/issues?q=is%3Aissue) and found no 
similar issues.
   
   
   ### Version
   
   
   master @ `0c29961f45ee976ef61c6a5dfe7b38b40a6ec131` (2026-09-30), built from 
source. Also
   4.1.4-rc04 (`doris-4.1.4-rc04-ad35a140c7f`) and 4.1.3-rc02.
   
   ### What's Wrong?
   
   
   A nonzero DOUBLE constant whose magnitude is below the smallest float32 
subnormal
   (~1.4e-45) is treated as **false** whenever it is converted to a boolean at 
plan time. That
   covers an explicit `CAST(... AS BOOLEAN)`, `IF(x, ...)`, `CASE WHEN x`, `x 
AND ...`, and
   `WHERE x`. The same engine agrees the value is nonzero (`x > 0` is 1, `x = 
0` is 0), and the
   same value read from a column is true.
   
   ```sql
   SELECT CAST('5e-324' AS DOUBLE) > 0;                       -- 1
   SELECT CAST('5e-324' AS DOUBLE) = 0;                       -- 0
   SELECT CAST(CAST('5e-324' AS DOUBLE) AS BOOLEAN);          -- 0   <-- wrong
   SELECT IF(CAST('5e-324' AS DOUBLE), 1, 0);                 -- 0   <-- wrong
   SELECT CASE WHEN CAST('5e-324' AS DOUBLE) THEN 1 ELSE 0 END;  -- 0 <-- wrong
   SELECT CAST(CAST('5e-324' AS DOUBLE) AND true AS INT);     -- 0   <-- wrong
   ```
   
   It affects real queries:
   
   ```sql
   SELECT count(*) FROM t WHERE CAST('5e-324' AS DOUBLE);     -- 0   (t has 4 
rows)
   ```
   
   The boundary is exactly float32 underflow:
   
   | value | `CAST(literal AS BOOLEAN)` | `CAST(column AS BOOLEAN)` | 
`CAST(literal AS FLOAT)` |
   |---|---|---|---|
   | `5e-324`, `1e-320`, `1e-300`, `1e-46` | **0** | 1 | `0.0` |
   | `1e-45`, `1e-10`, `0.5` | 1 | 1 | nonzero |
   | `0.0` | 0 | 0 | `0.0` |
   
   `EXPLAIN SELECT CAST(CAST('5e-324' AS DOUBLE) AS BOOLEAN)` shows the 
constant already folded
   to `FALSE` in the plan. `SET debug_skip_fold_constant = true` does not 
change the result.
   
   **Root cause (master @ `0c29961f`).**
   
`fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/FractionalLiteral.java:89-97`
 (line 92),
   in `uncheckedCastTo(BooleanType)`:
   
   ```java
   if (value instanceof Float || value instanceof Double) {
       if (((Number) value).floatValue() == 0) {   // narrows the double to 
float first
           return BooleanLiteral.FALSE;
   ```
   
   `floatValue()` rounds every double with |x| < ~1.4e-45 to `0.0f`. Using
   `((Number) value).doubleValue() == 0` instead gives the BE's answer (it is 
exact for both
   `Float` and `Double`). The BE's double→bool cast tests the double itself, 
which is
   why the column path is right.
   
   
   
   ### What You Expected?
   
   `CAST(x AS BOOLEAN)` is true for every nonzero DOUBLE, as in the BE (column 
path) and as the
   engine's own `x != 0` says: 1 for every row in the table above except `0.0`. 
Constant folding
   should not change the result of an expression.
   
   ### How to Reproduce?
   
   
   Single FE + single BE, default configuration.
   
   ```sql
   CREATE DATABASE d; USE d;
   CREATE TABLE t (i INT) DUPLICATE KEY(i)
     DISTRIBUTED BY HASH(i) BUCKETS 1 PROPERTIES('replication_num'='1');
   INSERT INTO t VALUES (0),(1),(2),(3);
   CREATE TABLE v (i INT, c DOUBLE) DUPLICATE KEY(i)
     DISTRIBUTED BY HASH(i) BUCKETS 1 PROPERTIES('replication_num'='1');
   INSERT INTO v VALUES (0, CAST('5e-324' AS DOUBLE));
   
   -- folded constant: wrong
   SELECT CAST(CAST('5e-324' AS DOUBLE) AS BOOLEAN);              -- 0
   SELECT IF(CAST('5e-324' AS DOUBLE), 1, 0);                     -- 0
   SELECT count(*) FROM t WHERE CAST('5e-324' AS DOUBLE);         -- 0
   -- same value from a column: right
   SELECT CAST(c AS BOOLEAN), IF(c, 1, 0) FROM v;                 -- 1, 1
   SELECT count(*) FROM t WHERE (SELECT c FROM v);                -- 4
   -- the engine agrees it is nonzero
   SELECT CAST('5e-324' AS DOUBLE) > 0, CAST('5e-324' AS DOUBLE) = 0;  -- 1, 0
   -- the boundary is float32 underflow
   SELECT CAST(CAST('1e-45' AS DOUBLE) AS BOOLEAN),
          CAST(CAST('1e-46' AS DOUBLE) AS BOOLEAN);               -- 1, 0
   ```
   
   ### Anything Else?
   
   
   The same sweep found a second FE/BE folding divergence, which might be fixed 
in the same pass:
   `acosh` and `asinh` overflow when folded.
   
   ```sql
   SELECT acosh(CAST('1.7976931348623157e308' AS DOUBLE)),
          asinh(CAST('1.7976931348623157e308' AS DOUBLE));   -- inf, inf
   -- same value (DBL_MAX) from a DOUBLE column:             -- 
710.4758600739439, 710.4758600739439
   ```
   
   The folded path is `NumericArithmetic.asinh` / `acosh`
   
(`fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/NumericArithmetic.java:672-689`),
   which calls commons-math `FastMath.asinh` / `FastMath.acosh`. Those return 
`inf` for `DBL_MAX`
   (presumably the `x*x` in `log(x + sqrt(x*x ± 1))` overflows), while the BE 
returns the finite result.
   
   
   ### Are you willing to submit PR?
   
   - [ ] Yes I am willing to submit a PR!
   
   ### Code of Conduct
   
   - [x] I agree to follow this project's [Code of 
Conduct](https://www.apache.org/foundation/policies/conduct)
   


-- 
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