cloud-fan opened a new pull request, #57265:
URL: https://github.com/apache/spark/pull/57265

   ### What changes were proposed in this pull request?
   
   In `XmlInferSchema.inferFrom`, stop skipping empty values during schema 
inference. Previously the guard was:
   
   ```scala
   if (value == null || value.isEmpty || value == options.nullValue) {
     return typeSoFar
   }
   ```
   
   This PR drops the `value.isEmpty` term:
   
   ```scala
   if (value == null || value == options.nullValue) {
     return typeSoFar
   }
   ```
   
   so an empty value now falls through the type cascade to `StringType`. As a 
result, a field mixing empty and numeric values widens to `StringType` instead 
of being inferred as the numeric type.
   
   ### Why are the changes needed?
   
   XML schema inference was copied from `CSVInferSchema.inferField`, which does 
early-return on `field.isEmpty`. But the two datasources have a crucial 
difference at parse time:
   
   - CSV defaults `nullValue` to `""`, so an empty field is read as null by the 
parser (`UnivocityParser.nullSafeDatum`). Its inference can safely skip empty 
values because they never reach a numeric converter.
   - XML defaults `nullValue` to `null`, so an empty value is **not** read as 
null. If a column mixing empty and numeric values inferred `LongType`, 
`StaxXmlParser` would call `convertTo("", LongType)`, which throws 
`NumberFormatException`. In `PERMISSIVE` mode (the default), the 
malformed-record error recovery can then silently consume sibling XML events, 
**dropping records** — a silent data-loss bug.
   
   Concretely, for input
   
   ```xml
   <ROW><entry Code="001">first</entry><entry Code="002">second</entry></ROW>
   <ROW><entry Code="">third</entry><entry Code="003">fourth</entry></ROW>
   <ROW><entry Code="004">fifth</entry><entry Code="">sixth</entry></ROW>
   ```
   
   `entry._Code` was inferred as `LongType` (from the numeric `Code` values, 
empty skipped), and reading then dropped records when it hit the empty 
`Code=""`. After this change `_Code` infers as `StringType` and all rows are 
read.
   
   By letting empty values fall through to `StringType`, inference stays 
consistent with how the XML parser actually reads the data.
   
   ### Does this PR introduce _any_ user-facing change?
   
   Yes. With the default `nullValue` (unset), a field that mixes empty and 
typed (e.g. numeric) values is now inferred as `StringType` instead of the 
typed type. This prevents the silent record-dropping described above. Fields 
that are entirely typed, or that use a non-default `nullValue` covering the 
empty token, are unaffected. Empty *elements* (`<c/>`) are still read as 
`NullType` by the parser and are unaffected.
   
   ### How was this patch tested?
   
   Added two tests to `XmlInferSchemaSuite`:
   
   - `SPARK-58133: empty values are not skipped during inference (no data 
loss)` — asserts that an attribute mixing empty and numeric values infers 
`StringType` and that all rows/entries survive (no PERMISSIVE-mode record 
dropping).
   - `SPARK-58133: empty and numeric element values still infer via NullType` — 
documents that empty elements keep inferring `LongType` (via the parser's 
`NullType` path), pinning the element/attribute asymmetry.
   
   Existing XML inference suites pass.
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Code (Anthropic Claude Opus)
   


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