SEPURI-SAI-KRISHNA opened a new issue, #11926:
URL: https://github.com/apache/seatunnel/issues/11926

   ### Search before asking
   
   - [x] I had searched in the 
[issues](https://github.com/apache/seatunnel/issues?q=is%3Aissue+label%3A%22bug%22)
 and found no similar issues.
   
   
   ### What happened
   
   Two numeric functions in the Zeta SQL transform narrow an integral result 
without checking that it fits, so a positive input silently produces a 
**negative** output. No exception is raised — the job reports success and 
writes the wrong number to the sink.
   
   **1. `ROUND` / `CEIL` / `CEILING` / `FLOOR` / `TRUNC` / `TRUNCATE` at 
negative scale**
   
   | Expression | Declared type | Actual | Expected |
   |---|---|---|---|
   | `ROUND(v, -1)` | SMALLINT, `v = 32767` | **-32766** | 32770, or an 
overflow error |
   | `ROUND(v, -1)` | INT, `v = 2147483647` | **-2147483646** | 2147483650, or 
an overflow error |
   | `ROUND(v, -1)` | BIGINT, `v = 9223372036854775807` | 
**-9223372036854775806** | overflow error |
   
   **2. `ABS` at the minimum negative value**
   
   | Expression | Declared type | Actual | Expected |
   |---|---|---|---|
   | `ABS(v)` | INT, `v = -2147483648` | **-2147483648** | exception |
   | `ABS(v)` | BIGINT, `v = -9223372036854775808` | **-9223372036854775808** | 
exception |
   
   For `ABS` the expected behaviour is not a matter of opinion — it is already 
written down. `docs/en/transforms/sql-functions.md` states:
   
   > Note that TINYINT, SMALLINT, INT, and BIGINT data types cannot represent 
absolute values of their minimum negative values, because they have more 
negative values than positive. For example, for INT data type allowed values 
are from -2147483648 to 2147483647. ABS(-2147483648) should be 2147483648, but 
this value is not allowed for this data type. **It leads to an exception.** To 
avoid it cast argument of this function to a higher data type.
   
   The documented contract is an exception. The implementation returns a 
negative absolute value instead, which is the one outcome the note exists to 
rule out.
   
   For the rounding family the docs specify `ROUND(numeric[, digitsInt]) -> 
NUMERIC (same type)` and `CEIL | CEILING (numeric) -> NUMERIC (same type, scale 
0)`. Rounding a positive value *up* to a negative one satisfies neither reading 
of that contract.
   
   ### Root cause
   
   Both defects are the same mistake — an integral result is narrowed on the 
assumption that it fits.
   
   `seatunnel-transforms-v2/.../sql/zeta/functions/NumericFunction.java`
   
   `round(Number, Number, RoundingMode)` has **two independent** overflow 
points on the negative-scale path:
   
   ```java
   case "INTEGER":
   case "SHORT":
   case "LONG": {
       if (scale < 0) {
           long original = v1.longValue();
           long scaled = BigDecimal.valueOf(original)
                   .setScale(scale, roundingMode)
                   .longValue();          // (1) overflows for BIGINT
           if (original != scaled) {
               v1 = convertTo(t, scaled); // (2) overflows for INT / SMALLINT
           }
       }
       break;
   }
   ```
   
   1. `BigDecimal.longValue()` is documented to discard all but the low-order 
64 bits. `9223372036854775807` rounded up at scale `-1` is 
`9223372036854775810`, which wraps to `-9223372036854775806`.
   2. `convertTo` narrows with `intValue()` / `shortValue()`, which truncate 
the same way: `2147483650 -> -2147483646`, `32770 -> -32766`.
   
   `abs(List<Object>)` relies on `Math.abs`, which is documented to return the 
argument unchanged when it is `MIN_VALUE`:
   
   ```java
   if (arg instanceof Integer) {
       return Math.abs(arg.intValue());   // Math.abs(Integer.MIN_VALUE) == 
Integer.MIN_VALUE
   }
   if (arg instanceof Long) {
       return Math.abs(arg.longValue());  // same for Long.MIN_VALUE
   }
   ```
   
   Neither path is a regression from a recent change: the negative-scale block 
and `convertTo` both pre-date #11697, and #11697 modified only the `BIGDECIMAL` 
case and the `CEIL`/`FLOOR` return types.
   
   These are reachable from ordinary SQL. `ZetaSQLType` (`:463-471`) makes 
`ABS`/`ROUND`/`CEIL`/`CEILING`/`FLOOR`/`TRUNC`/`TRUNCATE` return the type of 
their first argument, so an INT column stays INT through the call.
   
   ### SeaTunnel Version
   
   dev (3.0.0-SNAPSHOT)
   
   ### SeaTunnel Config
   
   ```conf
   env {
     parallelism = 1
     job.mode = "BATCH"
   }
   
   source {
     FakeSource {
       plugin_output = "fake"
       schema = {
         fields {
           int_v = "int"
           long_v = "bigint"
           small_v = "smallint"
           abs_int = "int"
           abs_long = "bigint"
         }
       }
       rows = [
         {
           kind = INSERT
           fields = [2147483647, 9223372036854775807, 32767, -2147483648, 
-9223372036854775808]
         }
       ]
     }
   }
   
   transform {
     Sql {
       plugin_input = "fake"
       plugin_output = "out"
       query = "select ROUND(int_v, -1) as r_int, ROUND(long_v, -1) as r_long, 
ROUND(small_v, -1) as r_small, ABS(abs_int) as a_int, ABS(abs_long) as a_long 
from fake"
     }
   }
   
   sink {
     Console {
       plugin_input = "out"
     }
   }
   ```
   
   ### Running Command
   
   ```shell
   ./bin/seatunnel.sh --config ./config/repro.conf -e local
   ```
   
   ### Error Exception
   
   ```log
   None — this is silent data corruption; the job reports success.
   
   r_int   = -2147483646        (expected 2147483650, or an overflow error)
   r_long  = -9223372036854775806 (expected an overflow error)
   r_small = -32766             (expected 32770, or an overflow error)
   a_int   = -2147483648        (docs require an exception)
   a_long  = -9223372036854775808 (docs require an exception)
   ```
   
   ### Zeta or Flink or Spark Version
   
   Zeta (engine-independent — the bug is in the transform)
   
   ### Java or Scala Version
   
   Java 11 / Java 17
   
   ### Screenshots
   
   _No response_
   
   ### Are you willing to submit PR?
   
   - [x] 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]

Reply via email to