Skip to content

Commit acecd76

Browse files
committed
feat(kernel): consume the folded directResults execute()
The kernel's `Statement.execute()` is now the directResults call (databricks/databricks-sql-kernel#136): it returns either a terminal `ExecutedStatement` (the query finished within the server inline wait) or a still-running `ExecutedAsyncStatement`, instead of always blocking to terminal. `KernelDatabricksClient.execute_command` now feature-detects the arm (via `await_result`, present only on the async handle): - terminal -> build the result set from the `ExecutedStatement` as before; - still-running -> register the handle (so `cursor.cancel()` / `close()` reach it), then `await_result()` to drive it to terminal — preserving execute()'s blocking contract. `cursor.execute()` behaviour is unchanged for callers (still blocks to a ready result set); this just adapts to the kernel's new single result-or-handle return. Mid-run cancel still works via the `_sync_cancellers` canceller registered before execute. Tested e2e against a live warehouse: CREATE/INSERT commit, 100k read, error surfaces at execute, mid-run cancel (~130ms). Latency vs Thrift: SELECT 1 ~parity, range(100000) ~parity. Co-authored-by: Isaac Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
1 parent 85f8ba3 commit acecd76

1 file changed

Lines changed: 27 additions & 13 deletions

File tree

src/databricks/sql/backend/kernel/client.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -472,19 +472,33 @@ def execute_command(
472472
except Exception:
473473
# Canceller is best-effort; never block execute on it.
474474
pass
475-
executed = stmt.execute()
476-
# Execute succeeded: the kernel now owns the statement
477-
# lifecycle. It auto-closes the server statement when the
478-
# result stream is fully drained (``ExecutedStatement::
479-
# next_batch`` end-of-stream), with the executed handle's
480-
# ``Drop`` as the backstop for partial/abandoned reads.
481-
# So we must NOT close ``stmt`` here: a premature
482-
# ``CloseStatement`` at execute-return broke lazy
483-
# CloudFetch chunk-link fetches (``get_result_chunks``
484-
# against the live statement) for large paginated-link
485-
# results. Closing here is left ONLY for the error path
486-
# below, where no executed handle / result set was
487-
# produced to reap it.
475+
# ``execute()`` is now the kernel's directResults call: it returns
476+
# either a terminal ``ExecutedStatement`` (finished within the
477+
# server inline wait) or an ``ExecutedAsyncStatement`` (still
478+
# running). Feature-detect via ``await_result`` (only on the
479+
# async arm).
480+
result = stmt.execute()
481+
if hasattr(result, "await_result"):
482+
# Still-running arm. Register the handle so ``cursor.cancel()``
483+
# (cancel_command) and ``close_command`` can reach it, then
484+
# drive it to terminal — preserving ``execute()``'s blocking
485+
# contract. The ``_sync_cancellers`` canceller registered
486+
# above also covers a cancel issued during this drive.
487+
command_id = CommandId.from_sea_statement_id(result.statement_id)
488+
cursor.active_command_id = command_id
489+
with self._async_handles_lock:
490+
self._async_handles[command_id.guid] = result
491+
self._async_statements[command_id.guid] = stmt
492+
close_stmt = False
493+
stream = result.await_result()
494+
return self._make_result_set(stream, cursor, command_id)
495+
# Terminal arm: an ``ExecutedStatement`` with the result inline.
496+
executed = result
497+
# The kernel now owns the statement lifecycle (auto-closes on
498+
# stream drain, with ``Drop`` as backstop), so we must NOT close
499+
# ``stmt`` here — a premature ``CloseStatement`` breaks lazy
500+
# CloudFetch chunk-link fetches. Closing is left to the error
501+
# path below.
488502
close_stmt = False
489503
except Exception as exc:
490504
raise _wrap_kernel_exception("execute_command", exc) from exc

0 commit comments

Comments
 (0)