cloud-fan commented on code in PR #57085:
URL: https://github.com/apache/spark/pull/57085#discussion_r3595819693


##########
docs/sql-migration-guide.md:
##########
@@ -29,6 +29,7 @@ license: |
 - Since Spark 4.3, the Spark Thrift Server rejects setting JVM system 
properties through the `set:system:` session configuration overlay (for 
example, in a JDBC connection string). To restore the previous behavior, set 
`spark.sql.legacy.hive.thriftServer.allowSettingSystemProperties` to `true`.
 - Since Spark 4.3, the adaptive execution rule 
`org.apache.spark.sql.execution.adaptive.DynamicJoinSelection` has been renamed 
to `DemoteBroadcastHashJoin`, which now only demotes broadcast hash joins 
(emitting `NO_BROADCAST_HASH`). Its selection of shuffled hash join over sort 
merge join has moved to a new physical rule gated by 
`spark.sql.adaptive.convertSortMergeJoinToShuffledHashJoin.enabled` (default 
`true`). If you previously disabled the shuffled-hash-join preference by 
listing `org.apache.spark.sql.execution.adaptive.DynamicJoinSelection` in 
`spark.sql.adaptive.optimizer.excludedRules`, that name no longer matches any 
rule (unknown names are silently ignored); set 
`spark.sql.adaptive.convertSortMergeJoinToShuffledHashJoin.enabled` to `false` 
instead.
 - Since Spark 4.3, the exact `percentile`, `percentile_cont`, and `median` 
aggregate functions (including their `WITHIN GROUP (ORDER BY ...)` forms) 
compute the linear interpolation between two neighboring values as `lower + 
fraction * (higher - lower)` instead of `(1 - fraction) * lower + fraction * 
higher`. The two are equal in exact arithmetic, but the new form is 
monotonically non-decreasing in the requested percentage and avoids a rounding 
error the old form could introduce. As a result these functions may return a 
value that differs from earlier releases in the last ULP. `percentile_disc` and 
`percentile_approx` are unaffected.

Review Comment:
   The prior-behavior claim here is not correct, and it changes what this entry 
should say. `TimestampToLongBase` extends `ExpectsInputTypes` (not 
`ImplicitCastInputTypes`), so the analyzer never implicitly cast a 
`TIMESTAMP_NTZ` argument to `TIMESTAMP_LTZ`. With the old `inputTypes = 
Seq(TimestampType)`, a `TIMESTAMP_NTZ` input was **rejected** with 
`DATATYPE_MISMATCH.UNEXPECTED_INPUT_TYPE` (verified in both ANSI and non-ANSI 
modes). So there was no prior (zone-shifted) result, and the `CAST(... AS 
TIMESTAMP_LTZ)` remediation reproduces nothing.
   
   This makes the change purely additive: previously-rejected types are now 
accepted. A pure capability addition normally doesn't need an "Upgrading" entry 
at all, since it can't change the result of any query that previously worked. 
If you keep a note, suggest reframing it as additive:
   
   ```suggestion
   - Since Spark 4.3, `unix_seconds`, `unix_millis`, and `unix_micros` accept 
`TIMESTAMP_NTZ` and the nanosecond-precision timestamp types directly, reading 
them with no time-zone shift. Previously these functions accepted only 
`TIMESTAMP_LTZ`; a `TIMESTAMP_NTZ` or nanosecond-timestamp argument was 
rejected with a `DATATYPE_MISMATCH` error. This is a new capability and does 
not change the result of any query that previously succeeded.
   ```



##########
sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala:
##########
@@ -1739,6 +1739,50 @@ class DateExpressionsSuite extends SparkFunSuite with 
ExpressionEvalHelper {
     checkEvaluation(UnixMicros(Literal(timestampWithNanos)), 1000001L)
   }
 
+  test("SPARK-57814: unix_seconds / unix_millis / unix_micros over " +
+    "NTZ and nanosecond-precision timestamps") {
+    import org.apache.spark.sql.catalyst.util.TimestampNanosTestUtils._
+
+    // 2008-12-25 15:30:00.123456789 -> epochMicros 1230219000123456 (+789 ns 
remainder dropped).
+    // unix_* apply no zone shift, so the NTZ wall-clock value and the LTZ 
instant at the same UTC
+    // reading produce identical results.
+    val ntz = localDateTimeToNanosVal(timestampNTZ(2008, 12, 25, 15, 30, 0, 
123456789))
+    val ltz = 
instantToNanosVal(Instant.parse("2008-12-25T15:30:00.123456789Z"))
+    foreachNanosPrecision { p =>
+      checkEvaluation(UnixSeconds(Literal.create(ntz, 
TimestampNTZNanosType(p))), 1230219000L)
+      checkEvaluation(UnixSeconds(Literal.create(ltz, 
TimestampLTZNanosType(p))), 1230219000L)
+      checkEvaluation(UnixMillis(Literal.create(ntz, 
TimestampNTZNanosType(p))), 1230219000123L)
+      checkEvaluation(UnixMillis(Literal.create(ltz, 
TimestampLTZNanosType(p))), 1230219000123L)
+      checkEvaluation(UnixMicros(Literal.create(ntz, 
TimestampNTZNanosType(p))), 1230219000123456L)
+      checkEvaluation(UnixMicros(Literal.create(ltz, 
TimestampLTZNanosType(p))), 1230219000123456L)
+    }
+
+    // Micro TIMESTAMP_NTZ is now accepted directly and read as a physical 
Long with no zone shift.
+    // It was NOT rejected before this change: implicit coercion silently cast 
it to TIMESTAMP_LTZ,

Review Comment:
   This comment's premise is incorrect (same root as the migration-guide note): 
micro `TIMESTAMP_NTZ` was **not** accepted-via-silent-coercion before — it was 
rejected with `DATATYPE_MISMATCH`, because `TimestampToLongBase` uses 
`ExpectsInputTypes`, which does no implicit casting. So there was no "old 
shift" to reintroduce, and the `Cast(microNtz, TimestampType, LA)` lines are 
not "the equivalent old coercion."
   
   The assertions are fine to keep — they're a useful contrast showing that 
reading NTZ directly (zoneless) differs from explicitly casting it to 
`TIMESTAMP_LTZ` under a non-UTC zone. Please just fix the comment so it doesn't 
record the false prior-behavior story, e.g. describe the explicit-cast lines as 
a contrast between direct (zoneless) NTZ reads and an explicit `TIMESTAMP_LTZ` 
cast, rather than as the previous implicit behavior.



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