dbtsai opened a new pull request, #59474:
URL: https://github.com/apache/spark/pull/59474

   ### What changes were proposed in this pull request?
   
   Teach the DataFrame query context frame filter (`sparkCodePattern` in 
`CurrentOrigin`, `sql/api`) to recognize the frames that typed UDF columns are 
constructed through, so the captured call site skips them and lands on the 
user's code:
   
   - `org.apache.spark.sql.expressions.UserDefinedFunction` — every UDF column 
is created via `UserDefinedFunction.apply(Column*)`.
   - `org.apache.spark.sql.connect.KeyValueGroupedDatasetImpl` (and the 
abstract `KeyValueGroupedDataset`) — the Connect client's `groupByKey` builds 
its grouping UDF inside this factory.
   
   Follow-up to SPARK-60226 (which added server-side operation labels and 
preserved the client-supplied origin in the Connect planner). That change is 
correct, but the origin the client *supplies* could already point at Spark 
internals; this PR fixes the capture.
   
   ### Why are the changes needed?
   
   The Connect client encodes typed Dataset APIs (`groupByKey`, `filter`, 
`reduce`) as a scalar Scala UDF applied to `col("*")`, i.e. 
`udf.apply(col("*"))` (`sql/connect/common/.../connect/Dataset.scala`, 
`KeyValueGroupedDataset.scala`). The origin is captured in `Column.apply` via 
`CurrentOrigin.withOrigin`, whose immediate caller is 
`UserDefinedFunction.apply` (`UserDefinedFunction.scala:69`).
   
   `sparkCodePattern` matched `Column`/`Dataset`/`functions`/... but not 
`UserDefinedFunction` (nor the `groupByKey` factory 
`KeyValueGroupedDatasetImpl`). With the default 
`spark.sql.stackTracesInDataFrameContext=1`, the one captured "non-Spark" frame 
was therefore the internal `UserDefinedFunction.apply` (and for `groupByKey`, 
`KeyValueGroupedDatasetImpl.apply`) rather than the user's class/line.
   
   Trace for `groupByKey`: `Column.apply` (matched) -> 
`UserDefinedFunction.apply` (unmatched -> walk stops here) -> 
`KeyValueGroupedDatasetImpl.apply` -> `Dataset.groupByKey` -> user. After 
matching both intermediates, the walk reaches the user frame.
   
   ### Does this PR introduce _any_ user-facing change?
   
   Yes. The DataFrame query context for UDF-backed columns now points at user 
code. Before:
   
       == DataFrame ==
       "apply" was called from
       
org.apache.spark.sql.expressions.UserDefinedFunction.apply(UserDefinedFunction.scala:69)
   
   After: the call site is the user's application frame. Note this also 
improves the context for ordinary UDF usage (`df.select(myUdf(col("x")))`), 
classic and Connect, since all UDF columns go through 
`UserDefinedFunction.apply`.
   
   ### How was this patch tested?
   
   Added a `DatasetSuite` regression that builds a UDF column and asserts its 
captured query-context call site points to the test (user code) and not to 
`UserDefinedFunction`.
   
   Draft notes for reviewers:
   - I was unable to build/run locally in my environment; CI is the first real 
build/run. Please treat the test as provisional until CI confirms.
   - The `UserDefinedFunction` part is exercised by the added classic test. The 
`groupByKey`-specific `KeyValueGroupedDatasetImpl` frame is fixed by the same 
mechanism but is only reachable via the Connect client; a dedicated Connect 
end-to-end regression (e.g. a real client-generated grouping expression whose 
serialized payload is then corrupted, asserting the surfaced context points to 
user code) would be a good addition — happy to add it, or guidance on the 
preferred location is welcome.
   - Design question for reviewers: enumerating intermediate classes in 
`sparkCodePattern` follows the existing approach but is somewhat fragile to 
future typed-API refactors. An alternative is to capture the origin at the 
public typed-API entry points (wrap them in `withOrigin`). Feedback on the 
preferred direction appreciated.
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   Generated-by: Isaac
   
   This pull request and its description were written by Isaac.
   


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