eschutho opened a new pull request, #42900:
URL: https://github.com/apache/superset/pull/42900

   ### SUMMARY
   SQL Lab's "stop query" action has no effect on Databricks connections using 
the Python Connector driver (`databricks-sql-connector`), the officially 
recommended driver for new deployments. The engine spec never implemented 
`get_cancel_query_id`/`cancel_query`, so a stopped query keeps running on the 
warehouse until it finishes or times out on its own.
   
   ### FIX
   - Added `get_cancel_query_id`/`cancel_query` to 
`DatabricksPythonConnectorEngineSpec`, gated on the connection using 
Databricks' Statement Execution API (SEA) backend (`use_sea=True` in connection 
params).
     - The driver's only cancellation primitive is `Cursor.cancel()`, which 
needs a full command identifier tied to the session that ran the query. 
Superset always issues cancellation from a brand-new connection (see 
`sql_lab.cancel_query`), so the identifier has to be serializable and reusable 
elsewhere.
     - On a SEA connection, that identifier is a plain statement id, which the 
driver can turn back into a valid cancel target on any cursor via 
`CommandId.from_sea_statement_id(...)`. That's what's captured and replayed 
here.
     - On the default Thrift backend, the equivalent identifier requires an 
operation *secret* that the driver only holds on the live `CommandId` object of 
the executing cursor — it's never exposed through `cursor.query_id` or any 
other public/documented accessor. Rather than reconstructing that secret from 
private driver internals, `get_cancel_query_id` returns `None` for Thrift 
connections, so "stop query" fails explicitly instead of silently doing nothing.
   - Added `has_query_id_before_execute = False` so the cancel id is captured 
*after* the statement executes — the driver only populates 
`cursor.active_command_id` once a command has actually run.
   - `cancel_query` lets any error from the fresh cancel cursor propagate 
instead of swallowing it into a generic `False`/"could not cancel" result, 
since silently reporting a failed cancel as if it were handled would be 
misleading.
   
   ### NOT CHANGED
   - **Databricks Interactive Cluster (Hive-based) connections** — already work 
via `has_implicit_cancel` (the live cursor is closed to cancel server-side); 
out of scope here.
   - **ODBC (SQL Endpoints)** — pyodbc cursors expose `.cancel()` 
(`SQLCancel`), but like the Thrift case above, Superset's cancel flow uses a 
fresh cursor/connection with no reference to the one running the query, so it's 
unclear this would actually cancel anything. Left unimplemented pending 
real-world verification.
   - **Legacy `databricks-dbapi` connector** — already flagged in this file as 
legacy ("Use Python Connector for new deployments"); not worth building cancel 
support for.
   - **Thrift backend (the default) on the Python Connector** — see above; this 
PR only covers SEA-enabled connections. Connections using the default 
configuration will see no behavior change.
   
   ### TESTING INSTRUCTIONS
   Added unit tests in `tests/unit_tests/db_engine_specs/test_databricks.py` 
covering:
   - `get_cancel_query_id` returns the SEA statement id when `use_sea=True`
   - `get_cancel_query_id` returns `None` when no command has executed yet
   - `get_cancel_query_id` returns `None` on the default (non-SEA) backend — 
this is intended behavior, not a gap
   - `cancel_query` reconstructs the SEA command id and delegates to the 
driver's `cursor.cancel()`
   - `cancel_query` rejects a malformed cancel id without touching the cursor
   - `cancel_query` propagates errors from the cancel attempt instead of 
swallowing them
   
   Ran `pytest tests/unit_tests/db_engine_specs/test_databricks.py 
tests/unit_tests/db_engine_specs/test_base.py` (138 passed) and the full 
`tests/unit_tests/db_engine_specs/` suite (1265 passed, 9 
pre-existing/unrelated failures in `test_bigquery.py` and `test_mysql.py` 
reproduced identically on `master`, caused by local environment dependency 
versions, not this change).
   
   Ran `pre-commit` (ruff, ruff-format, mypy, pylint, db-engine-spec-metadata) 
on the changed files — all passed.
   
   ### ADDITIONAL INFORMATION
   - [ ] Has associated issue:
   - [ ] Required feature flags:
   - [ ] Changes UI
   - [ ] Includes DB Migration (follow approval process in 
[SIP-59](https://github.com/apache/superset/issues/13351))
     - [ ] Migration is atomic, supports rollback & is backwards-compatible
     - [ ] Confirm DB migration upgrade and downgrade tested
     - [ ] Runtime estimates and downtime expectations provided
   - [x] Introduces new feature or API
   - [ ] Removes existing feature or API
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


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