snmvaughan opened a new issue, #7581:
URL: https://github.com/apache/datafusion-comet/issues/7581

   ### Describe the bug
   
   The native string to decimal cast parses the digits of a string into an 
`i128`, so a string with more than 38 digits after its leading zeros, or with 
more than 38 fractional digits, fails to parse. `java.math.BigDecimal`, which 
Spark parses with, has no such limit. Comet returns NULL, or raises 
`CAST_INVALID_INPUT` under ANSI mode, where Spark returns a value or a 
different error.
   
   | Input, cast to the target type | Spark 4.1.3 | Comet |
   |---|---|---|
   | `'1.'` and 50 zeros, to `DECIMAL(10,2)` | `1.00` | NULL 
(`CAST_INVALID_INPUT` under ANSI) |
   | `'0.'`, 40 zeros and `'1'`, to `DECIMAL(10,2)` | `0.00` | NULL 
(`CAST_INVALID_INPUT` under ANSI) |
   | `'1'` and 39 zeros, to `DECIMAL(10,-35)`, with the setting below | 
`1.0000E+39` | NULL (`CAST_INVALID_INPUT` under ANSI) |
   | `'1'` and 39 zeros, to `DECIMAL(10,2)`, with the setting below | NULL 
(`NUMERIC_VALUE_OUT_OF_RANGE` under ANSI) | NULL (`CAST_INVALID_INPUT` under 
ANSI) |
   
   The last two rows need `spark.sql.legacy.allowNegativeScaleOfDecimal=true`. 
Without it, Spark rejects the 40-digit string before it rescales it: NULL, or 
`NUMERIC_OUT_OF_SUPPORTED_RANGE` under ANSI. The first two rows need no setting.
   
   ### Steps to reproduce
   
   ```sql
   SET spark.sql.ansi.enabled=false;
   CREATE TABLE t (s STRING) USING parquet;
   INSERT INTO t VALUES 
('1.00000000000000000000000000000000000000000000000000');
   SELECT CAST(s AS DECIMAL(10, 2)) FROM t;
   -- Spark: 1.00
   -- Comet: NULL
   ```
   
   The value comes from a table so that the optimizer doesn't fold the cast 
before Comet sees it. With `spark.sql.ansi.enabled=true`, Comet raises 
`CAST_INVALID_INPUT` and Spark returns `1.00`.
   
   ### Expected behavior
   
   The native cast returns what Spark returns: the rounded value for the first 
two rows, `1.0000E+39` for the negative-scale target, and 
`NUMERIC_VALUE_OUT_OF_RANGE` under ANSI where the value is too large for the 
target type.
   
   ### Additional context
   
   - The limit is in `parse_decimal_str` in 
`native/spark-expr/src/conversion_funcs/string.rs`. `digits_to_i128` fails on 
the integral or the fractional digits, and `pow10_i128(fractional_scale)` has 
no entry above 10^38. Both map to `invalid_decimal_cast`.
   - Spark rounds `HALF_UP`, so only the digits up to the target scale and the 
first digit after it decide the result. A fix can work on the digit string and 
does not need an integer type wider than `i128`.
   - Related: #7576 is the same function reporting the wrong error for a scale 
adjustment over 38, which is a one-line change. #7188 and #7578 make a string 
with more than 38 integral digits raise `NUMERIC_OUT_OF_SUPPORTED_RANGE`, as 
Spark does, when the setting is off.
   
   ### Willingness to contribute
   
   I can contribute a fix for this bug independently.
   


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