SEPURI-SAI-KRISHNA commented on PR #12605:
URL: https://github.com/apache/seatunnel/pull/12605#issuecomment-5946998265

   Thanks, this is a careful review and Issue 1 was a real defect. All four are 
addressed, as a follow-up commit rather than a force-push so the delta is 
reviewable.
   
   Two parts of your suggested fix I did not take. Both are deliberate, and I 
would rather set out the reasoning and let you decide than quietly diverge.
   
   ## Issue 1, confirmed and fixed
   
   Reproduced before changing anything. On the previous head:
   
   | input to `CAST(... AS INT)` | result |
   | --- | --- |
   | `BigDecimal` `18446744073709551621` (2^64+5) | `5` |
   | `BigDecimal` `18446744073709551616` (2^64) | `0` |
   | `Double` `NaN` | `0` |
   
   Reachable exactly as you said: `COALESCE(c_int, c_dec)` with a 
`DECIMAL(38,0)` second argument types as `INT` and emitted `5`.
   
   The helper now truncates towards zero per numeric family and range-checks 
the truncated value:
   
   - `BigDecimal` and `BigInteger` through `toBigInteger()` and a `BigInteger` 
comparison against the int bounds.
   - `Double` and `Float` reject `NaN` and the infinities explicitly, then 
narrow to `long`.
   - `Byte`, `Short`, `Integer`, `Long` keep the `long` check, which is exact 
for them.
   
   The infinity check is strictly redundant, since narrowing an infinity to 
`long` saturates outside the int range anyway, but I kept it so the intent is 
readable rather than implied by two conversions.
   
   ## Deviation 1: not `intValueExact()`
   
   `intValueExact()` throws on a fractional part as well as on overflow. 
`CAST(5.7 AS INT)` returns `5` today, so adopting it would change fraction 
handling alongside range handling. It would also leave `BigDecimal` rejecting 
`5.7` while `Double` still truncated it, which replaces one source-type 
inconsistency with another.
   
   So this PR keeps truncation and changes only range behaviour.
   
   ## Deviation 2: truncate first, then range-check
   
   Your Double/Float guidance was to compare the `double` against the bounds 
**before narrowing**. I do the opposite, because comparing first rejects a 
fractional value whose truncation is in range. My first attempt followed the 
wording literally and had that bug:
   
   ```
   CAST(2147483647.5 AS INT)    today: 2147483647
                                compare-before-narrow: error     <- wrong
                                truncate-then-check: 2147483647
   ```
   
   `-2147483648.5` and the `BigDecimal` equivalents behaved the same way. 
`testCastAsIntTruncatesBeforeRangeCheckingAFractionalSource` pins all four, 
plus the four one-step-beyond values that must still fail, and there is a 
comment at the line so the order does not get "simplified" back later.
   
   ## Issues 2, 3 and 4
   
   **Issue 2.** Both reference pages are cut to the current contract and scoped 
to the types that enforce it, so `BIGINT` is no longer covered by the sentence. 
The history is gone from the function reference and stays in 
`incompatible-changes.md`, which now also records the wide-numeric and `NaN` 
cases, the unchanged fraction behaviour, and that `BIGINT` is not range-checked 
by this change.
   
   **Issue 3.** The message is now `Value %s cannot be converted to %s: out of 
range [%d, %d]`, from a small `outOfIntRange` helper whose javadoc records why 
it does not say `CAST`. The redundant `(long)` casts are gone. I left 
`UNSUPPORTED_OPERATION` as you suggested, since it matches the neighbouring 
branches; happy to introduce a dedicated code if you would rather, though that 
felt like a wider change than one branch warrants.
   
   **Issue 4.** Javadoc is now the contract plus `@throws TransformException` 
and a pointer to #12571.
   
   ## Three questions
   
   1. **Fractions.** You asked me to decide explicitly, so: this PR keeps 
truncation, which still differs from the string path where 
`Integer.parseInt("5.7")` fails. Would you prefer them aligned, with `CAST(5.7 
AS INT)` failing? I did not do it because it is a second behaviour change on 
top of the range one, but if you want it I would rather do it here than leave 
the inconsistency documented and open.
   
   2. **`BIGINT` has the same defect.** Your Issue 2 made me check it, and it 
does, which I had not realised:
   
      | input to `CAST(... AS BIGINT)` | result on `dev` today |
      | --- | --- |
      | `BigDecimal` 2^64+5 | `5` |
      | `BigDecimal` 2^64 | `0` |
      | `Double` `NaN` | `0` |
      | `Double` `1e30` | `9223372036854775807` |
   
      The same helper shape would fix it. I left it out because the agreed 
scope on #12571 was `TINYINT`, `SMALLINT` and `INT`, and because it widens the 
behaviour change again. Do you want it folded in here, or as a separate PR 
against a separate issue?
   
   3. **Scope check.** With `BIGINT` excluded, the incompatible-changes entry 
has to say so, which rather invites "why not". If your answer to 2 is "separate 
PR", I will file the issue straight away and link it from the entry so it does 
not read as an oversight.
   
   ## Verification
   
   `seatunnel-transforms-v2` is green at 1169 tests, reproduced across repeat 
runs, `spotless:check` passes. Two mutation checks: reverting to the plain 
`longValue()` widening fails 
`testCastAsIntRejectsWideAndNonFiniteNumericSources` on `BigDecimal` 2^64+5, 
and comparing the raw double instead of the truncated one fails the new 
boundary test on `2147483647.5`.
   


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

Reply via email to