MaxGekk commented on code in PR #56854:
URL: https://github.com/apache/spark/pull/56854#discussion_r3489805481


##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/xml/XmlInferSchema.scala:
##########
@@ -641,8 +650,44 @@ object XmlInferSchema {
     (t1: DataType, t2: DataType): DataType = {
 
     // TODO: Optimise this logic.
+    // AnyTimestampNanoType extends DatetimeType but is not covered by 
findWiderDateTimeType;
+    // handle it first to avoid a MatchError inside 
TypeCoercion.findTightestCommonType.
+    // StructType and ArrayType are also handled here so that compatibleType 
is used recursively
+    // for nested field types, preserving the nano-timestamp downgrade logic 
at all nesting levels.
+    // (TypeCoercion.findTightestCommonType handles same-structure 
StructType/ArrayType via
+    // findTypeForComplex, which calls findWiderDateTimeType and would bypass 
the custom logic.)
+    (t1, t2) match {
+      case (n1: TimestampNTZNanosType, n2: TimestampNTZNanosType) =>
+        return TimestampNTZNanosType(math.max(n1.precision, n2.precision))
+      case (n1: TimestampLTZNanosType, n2: TimestampLTZNanosType) =>
+        return TimestampLTZNanosType(math.max(n1.precision, n2.precision))
+      case (_: TimestampNTZNanosType, TimestampNTZType) |
+          (TimestampNTZType, _: TimestampNTZNanosType) =>
+        return TimestampNTZType
+      case (_: AnyTimestampNanoType, _) | (_, _: AnyTimestampNanoType) =>

Review Comment:
   This catch-all matches a nano type paired with *any* type, and it precedes 
the `StructType`/`ArrayType` cases below. So a field inferred as a nano 
timestamp in one record and a non-datetime (`Long`, `Decimal`, `String`, 
`Struct`, `Array`) in another widens to `TimestampType`, whereas the 
micro-precision path and every other incompatible combination fall through to 
`case (_, _) => StringType` (line 747). The non-timestamp rows would then fail 
/ become `null` at read.
   
   The `MatchError`-avoidance motive only needs nano-vs-*datetime* to be 
intercepted before `findTightestCommonType`, so narrowing the other side to 
`DatetimeType` keeps that protection while letting nano-vs-non-datetime fall 
through to the `StringType` default, matching the micro path:
   
   ```suggestion
         case (_: AnyTimestampNanoType, _: DatetimeType) | (_: DatetimeType, _: 
AnyTimestampNanoType) =>
   ```
   
   (`DatetimeType` is already in scope via the `org.apache.spark.sql.types._` 
import.)



##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/xml/StaxXmlParser.scala:
##########
@@ -601,6 +601,9 @@ class StaxXmlParser(
           Decimal(decimalParser(datum), dt.precision, dt.scale)
         case _: TimestampType => parseXmlTimestamp(datum, options)
         case _: TimestampNTZType => 
timestampNTZFormatter.parseWithoutTimeZone(datum, false)
+        case t: TimestampLTZNanosType => timestampFormatter.parseNanos(datum, 
t.precision)
+        case t: TimestampNTZNanosType =>
+          timestampNTZFormatter.parseWithoutTimeZoneNanos(datum, t.precision)

Review Comment:
   This calls the 2-arg `parseWithoutTimeZoneNanos(s, precision)` overload, 
which fixes `allowTimeZone = true` (`TimestampFormatter.scala:240`). So a 
zone-bearing value (e.g. `2025-06-15T12:30:45.123456789+05:00`) read into a 
`TIMESTAMP_NTZ(p)` column is silently accepted with the zone dropped — 
`extractNanosNTZ` only throws when `!allowTimeZone`.
   
   The adjacent micro `TimestampNTZType` path (line 603, 
`parseWithoutTimeZone(datum, false)`), the inference path 
(`parseWithoutTimeZoneNanosOptional(field, 9, false)`), and the CSV analogue 
(`UnivocityParser.scala`, `parseWithoutTimeZoneNanos(datum, t.precision, 
false)`) all pass `false` and reject zoned input as a malformed record. Suggest 
matching that contract here:
   
   ```suggestion
             timestampNTZFormatter.parseWithoutTimeZoneNanos(datum, 
t.precision, false)
   ```



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