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

   ### What changes were proposed in this pull request?
   
   Two commits:
   
   1. `GrpcExceptionConverter` now preserves the original 
`StatusRuntimeException`
      as the cause of fallback errors (errors without `ErrorInfo`), generalizing
      what the `DEADLINE_EXCEEDED` branch already did for the same reason.
   2. The Connect JDBC driver maps client failures to `SQLException` at the two
      points where they cross the JDBC boundary: `SparkConnectStatement.execute`
      (`executeQuery`/`executeUpdate` route through it) and
      `SparkConnectResultSet.next` (rows are fetched lazily, so errors during
      result streaming surface there).
   
   | Error | Mapped to | SQLState |
   |---|---|---|
   | `INVALID_HANDLE.SESSION_*` (session is gone) | 
`SQLNonTransientConnectionException` | `08003` |
   | gRPC `UNAVAILABLE` | `SQLTransientConnectionException` | `08006` |
   | gRPC `DEADLINE_EXCEEDED` | `SQLTimeoutException` | `HYT00` |
   | Anything else | `SQLException` | server-provided |
   
   The gRPC status is read only from the `StatusRuntimeException` preserved in
   the cause chain (commit 1), never from message text, so a server-side error
   that merely quotes a gRPC exception cannot be mistaken for a transport
   failure. The original exception is always kept as the cause.
   
   Notes on the mapping:
   - Operation-level `INVALID_HANDLE` subconditions (`OPERATION_*`, `FORMAT`)
     are not connection errors: the session is still healthy.
   - `DEADLINE_EXCEEDED` is a timeout, not a connection failure: a slow query
     fires it on a healthy connection, and the client's own `RetryPolicy`
     deliberately excludes it from retryable errors.
   
   Other JDBC entry points (`Connection.setCatalog`, `DatabaseMetaData` query
   methods, `Statement.cancel`) will be covered in a follow-up.
   
   ### Why are the changes needed?
   
   Currently unchecked exceptions (e.g. `SparkException`) leak across the JDBC
   boundary: standard JDBC code catching `SQLException` misses them, and there
   is no SQLState to act on. SQLState class 08 is how connection pools (e.g.
   HikariCP) and BI tools detect a dead connection and reconnect; without it
   they keep handing out a connection whose server-side session is gone.
   
   ### Does this PR introduce _any_ user-facing change?
   
   Yes, for the unreleased Connect JDBC driver:
   
       stmt.execute("SELECT * FROM nonexistent")
       // before: throws AnalysisException (unchecked)
       // after:  throws SQLException with getSQLState() == "42P01"
   
   For other Connect clients, the only observable change is that fallback
   `SparkException`s now carry the original `StatusRuntimeException` as their
   cause (previously often null); messages are unchanged.
   
   ### How was this patch tested?
   
   - `SparkConnectClientSuite`: new test that transport errors preserve the
     gRPC exception as the cause; existing deadline tests still pass.
   - New `JdbcErrorUtilsSuite`: 13 unit tests covering the mapping table,
     precedence, cause-chain traversal, and the quoted-gRPC-text negative case.
   - Integration tests: a failing query throws `SQLException`/`42P01` from
     `execute`; a mid-stream failure (ANSI divide-by-zero) throws
     `SQLException`/`22012` from `next`.
   
   Ran `build/sbt "connect-client-jdbc/test"` and scalastyle.
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Code (claude-fable-5)
   


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