You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by ur...@apache.org on 2026/08/13 05:50:59 UTC
(spark) branch master updated: [SPARK-58740][SQL][TEST] Add to_xml test coverage for nanosecond-precision timestamp types
This is an automated email from the ASF dual-hosted git repository.
uros-b pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git
The following commit(s) were added to refs/heads/master by this push:
new 94cbfbaf818a [SPARK-58740][SQL][TEST] Add to_xml test coverage for nanosecond-precision timestamp types
94cbfbaf818a is described below
commit 94cbfbaf818aa071eb989620aee4cf20a24133ad
Author: Stevo Mitric <st...@gmail.com>
AuthorDate: Thu Aug 13 05:50:45 2026 +0000
[SPARK-58740][SQL][TEST] Add to_xml test coverage for nanosecond-precision timestamp types
### What changes were proposed in this pull request?
This PR adds test coverage for the `to_xml` write path with the nanosecond-precision timestamp types (`TIMESTAMP_NTZ(p)` / `TIMESTAMP_LTZ(p)`, `p in [7, 9]`). The write path exists in `StaxXmlGenerator` but had no dedicated tests, while `from_xml` (read) and both JSON directions were already covered.
Two tests are added to `XmlFunctionsSuite`:
- `to_xml with nanos timestamp types` — asserts the exact XML output for both NTZ and LTZ nanos types at every valid precision.
- `roundtrip in to_xml and from_xml - nanos timestamps` — verifies the write -> read round-trip is loss-free at every valid precision.
### Why are the changes needed?
The `to_xml` nanosecond write path was implemented but never exercised by a test, leaving a coverage gap for the XML datasource nanosecond support (SPARK-57458).
### Does this PR introduce _any_ user-facing change?
No. Test-only change.
### How was this patch tested?
`build/sbt "sql/testOnly org.apache.spark.sql.XmlFunctionsSuite"`.
### Was this patch authored or co-authored using generative AI tooling?
Co-authored-by: Claude Code 4.8
Closes #57963 from stevomitric/stevomitric/spark-57458-to-xml-nanos-tests.
Lead-authored-by: Stevo Mitric <st...@gmail.com>
Co-authored-by: Uros Bojanic <22...@users.noreply.github.com>
Signed-off-by: Uros Bojanic <22...@users.noreply.github.com>
---
.../org/apache/spark/sql/XmlFunctionsSuite.scala | 63 ++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/sql/core/src/test/scala/org/apache/spark/sql/XmlFunctionsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/XmlFunctionsSuite.scala
index 73cdc7df139a..bfe46e681261 100644
--- a/sql/core/src/test/scala/org/apache/spark/sql/XmlFunctionsSuite.scala
+++ b/sql/core/src/test/scala/org/apache/spark/sql/XmlFunctionsSuite.scala
@@ -361,6 +361,69 @@ class XmlFunctionsSuite extends SharedSparkSession {
checkAnswer(dfTwo, readBackTwo)
}
+ test("SPARK-57458: to_xml with nanos timestamp types") {
+ withSQLConf(
+ SQLConf.TIMESTAMP_NANOS_TYPES_ENABLED.key -> "true",
+ SQLConf.SESSION_LOCAL_TIMEZONE.key -> "UTC") {
+ foreachNanosPrecision { p =>
+ // The pattern must carry `p` fractional digits to emit the full declared precision; the
+ // stored value is truncated to precision `p`, so the rendered fraction is the first
+ // `p` digits of 123456789.
+ val fracPat = "S" * p
+ val frac = "123456789".take(p)
+ val ldt = LocalDateTime.of(2020, 1, 1, 0, 0, 0, 123456789)
+ Seq(
+ (TimestampNTZNanosType(p): DataType, "timestampNTZFormat",
+ s"yyyy-MM-dd'T'HH:mm:ss.$fracPat", ldt: Any,
+ s"2020-01-01T00:00:00.$frac"),
+ (TimestampLTZNanosType(p): DataType, "timestampFormat",
+ s"yyyy-MM-dd'T'HH:mm:ss.${fracPat}XXX", ldt.toInstant(ZoneOffset.UTC): Any,
+ s"2020-01-01T00:00:00.${frac}Z")).foreach {
+ case (nanosType, optKey, fmt, value, expectedTs) =>
+ val schema = new StructType().add("ts", nanosType)
+ val df = spark.createDataFrame(
+ spark.sparkContext.parallelize(Seq(Row(value))), schema)
+ val expectedXml =
+ s"""|<ROW>
+ | <ts>$expectedTs</ts>
+ |</ROW>""".stripMargin
+ checkAnswer(
+ df.select(to_xml(struct($"ts"), Map(optKey -> fmt).asJava)),
+ Row(expectedXml))
+ }
+ }
+ }
+ }
+
+ test("SPARK-57458: roundtrip in to_xml and from_xml - nanos timestamps") {
+ withSQLConf(
+ SQLConf.TIMESTAMP_NANOS_TYPES_ENABLED.key -> "true",
+ SQLConf.SESSION_LOCAL_TIMEZONE.key -> "UTC") {
+ foreachNanosPrecision { p =>
+ val fracPat = "S" * p
+ val ldt = LocalDateTime.of(2020, 1, 1, 0, 0, 0, 123456789)
+ Seq(
+ (TimestampNTZNanosType(p): DataType, "timestampNTZFormat",
+ s"yyyy-MM-dd'T'HH:mm:ss.$fracPat", ldt: Any),
+ (TimestampLTZNanosType(p): DataType, "timestampFormat",
+ s"yyyy-MM-dd'T'HH:mm:ss.${fracPat}XXX", ldt.toInstant(ZoneOffset.UTC): Any)).foreach {
+ case (nanosType, optKey, fmt, value) =>
+ val schema = new StructType().add("ts", nanosType)
+ val df = spark.createDataFrame(
+ spark.sparkContext.parallelize(Seq(Row(value))), schema)
+ val options = Map(optKey -> fmt).asJava
+ // The input column already carries precision `p`, so the to_xml -> from_xml
+ // round-trip with a `p`-digit pattern is loss-free.
+ val readBack = df
+ .select(to_xml(struct($"ts"), options).as("xml"))
+ .select(from_xml($"xml", schema, options).as("data"))
+ .select($"data.ts".as("ts"))
+ checkAnswer(readBack, df.select($"ts"))
+ }
+ }
+ }
+ }
+
test("Support to_xml in SQL") {
val schemaOne = StructType(StructField("a", IntegerType, nullable = false) :: Nil)
val dataOne = Seq(Row(1))
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org