andygrove opened a new pull request, #5150:
URL: https://github.com/apache/datafusion-comet/pull/5150

   ## Which issue does this PR close?
   
   Part of #5149. This PR covers the first five subtasks of that epic; the 
timestamp targets and the latent `to_time.rs` trim are left for follow-ups.
   
   ## Rationale for this change
   
   Comet's cast-from-string kernels used four different trim sets, three of 
which diverge from Spark. Spark has exactly two trim regimes, and neither of 
them trims any non-ASCII whitespace:
   
   | Regime | Trimmed bytes | Cast targets |
   | --- | --- | --- |
   | `UTF8String.trimAll` | `0x00`-`0x20` and `0x7F` | boolean, byte, short, 
int, long, date, timestamp, timestamp_ntz |
   | `java.lang.String.trim` | `0x00`-`0x20` | float, double, decimal |
   
   Every affected cast is `Compatible()` in `CometCast.canCastFromString`, so 
all of them run natively by default. The divergence went in both directions: 
spurious failures where Spark parses fine, and silent wrong results (with the 
ANSI error swallowed) where Spark returns `NULL` or raises.
   
   ```sql
   -- before this PR
   SELECT CAST(concat(char(1), 'true') AS boolean);  -- Spark: true,  Comet: 
NULL (throws under ANSI)
   SELECT CAST(concat(char(1), '123')  AS int);      -- Spark: 123,   Comet: 
NULL (throws under ANSI)
   SELECT CAST(concat(' ', 'true') AS boolean);     -- Spark: NULL,  Comet: true
   SELECT CAST(concat(' ', '1.5')  AS double);      -- Spark: NULL,  Comet: 1.5
   ```
   
   ## What changes are included in this PR?
   
   - New `native/spark-expr/src/conversion_funcs/trim.rs` with the two regimes 
as explicit, documented helpers (`trim_all` / `trim_all_bytes` and 
`trim_java_string`), unit-tested against the byte sets themselves rather than 
against cast results.
   - `CAST(string AS boolean)` uses the `trimAll` set. The keyword comparison 
is now allocation-free (`eq_ignore_ascii_case`) instead of 
`to_ascii_lowercase()` per row.
   - `CAST(string AS byte/short/int/long)` uses the `trimAll` set in all three 
eval modes. `<[u8]>::trim_ascii` was excluding `0x0B`, which Spark trims.
   - `CAST(string AS float/double)` and `CAST(string AS decimal)` use the 
`String.trim` set, leaving `0x7F` untrimmed and preserving the existing NUL 
handling (NUL is in that set).
   - `date_parser` was already correct; it now shares the predicate instead of 
recomputing it, so there is one definition of the `trimAll` set.
   - Docs: the compatibility page documents both regimes; the boolean entry in 
the known-divergences list is replaced by an entry for the remaining timestamp 
divergence.
   
   Not in this PR (tracked on #5149): `CAST(string AS timestamp)` / 
`timestamp_ntz`, including `timestamp_parser`'s Spark-4 leading-whitespace 
gate, and the latent `to_time.rs` trim.
   
   ## How are these changes tested?
   
   - Rust: the trim helpers are tested byte-by-byte against Java's 
`Character.isWhitespace`/`isISOControl` definitions, plus a parity matrix 
(leading / trailing / both / interior position × all three eval modes) for 
every fixed cast target. Reverting any one of the four kernel changes fails the 
corresponding matrix test.
   - Scala: three new `CometCastSuite` tests run the same codepoint matrix 
through `castTest`, so real Spark is the oracle for values, `NULL`s and ANSI 
error messages.
   - Full `CometCastSuite` and the `cast` SQL-file tests pass on Spark 3.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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to