/* tslint:disable */ /* eslint-disable */ /* auto-generated by NAPI-RS */ /** * Per-statement options for `Connection.executeStatement`. * * Mirrors the kernel `StatementSpec` knobs that are safe to thread * through napi without a kernel-side change. Today this covers: * - `statementConf` — per-statement Spark conf overlay * (`StatementSpec.statement_conf` → SEA `parameters` / * Thrift `confOverlay`) * - `queryTags` — convenience wrapper over `statementConf` with * key `query_tags`; serialised to the same comma-separated * `key:value` wire shape NodeJS Thrift's `serializeQueryTags` * produces (`lib/utils/queryTags.ts`). Backslashes in keys are * doubled; backslash/colon/comma in values are backslash-escaped. * * `rowLimit` (SEA `row_limit`) is exposed here and threaded onto the kernel * `StatementSpec`. `positionalParams` (`?`) and `namedParams` (`:name`) * carry bound query parameters, decoded via `params::parse_typed_value`. * (There is no `queryTimeoutSecs`: it abused the SEA `wait_timeout` inline-hold * window and was removed — a real per-statement timeout is `STATEMENT_TIMEOUT`.) * * **Tag-order caveat (M4 parity note).** The napi `queryTags` field * is a Rust `HashMap` whose iteration order is * non-deterministic, so the serialised `query_tags` value may have * a different key order than Thrift's `serializeQueryTags` (which * iterates `Object.keys(...)` in insertion order) for the same * input. The SEA server is order-insensitive on conf values, so * the two are functionally equivalent. If a caller needs * byte-identical Thrift parity, the JS adapter pre-serialises via * `serializeQueryTags` and writes the result into * `statementConf["query_tags"]` directly — see * `KernelSessionBackend.executeStatement` in the NodeJS driver. This * path is the one the production code uses. */ export interface ExecuteOptions { /** * Per-statement Spark conf overlay. Merged on top of the * session-level `sessionConf` at execute time; this map wins * on key collisions. Unknown keys are rejected by the server. */ statementConf?: Record /** * Query tags as key→value pairs. Serialised to a comma- * separated `key:value` string (backslash-escaping `\`, `:`, * `,`) and placed into `statementConf["query_tags"]`, matching * NodeJS Thrift's `serializeQueryTags` wire shape. Passing * both `queryTags` AND a `query_tags` key in `statementConf` * raises `InvalidArgument` — the caller's intent is ambiguous * so we refuse to silently pick one over the other. * * A **`null`** value emits a **bare key** (no colon) — e.g. * `{ production: null }` → `"production"` — matching the * connectors' `key`-only tag form. * * See the struct-level "Tag-order caveat" for the * HashMap-iteration-order vs `Object.keys`-iteration-order * divergence and the byte-identical-Thrift-parity workaround. */ queryTags?: Record /** * Server-side cap on the number of rows this statement returns * (SEA `row_limit`), independent of any SQL `LIMIT`. Maps to * `StatementSpec.row_limit`. Omitted ⇒ no driver-imposed cap. */ rowLimit?: number /** * Positional parameters, in 1-based wire order. Index `i` in this * Vec corresponds to the `i+1`-th `?` placeholder in the SQL. * Each entry is a `{ sqlType, value }` pair — `value` is the * string-encoded literal or `null` for SQL NULL. Mirrors * `StatementSpec::positional_params`; decoded via [`parse_typed_value`]. */ positionalParams?: Array /** * Named parameters (`:name` placeholders). Each carries its `name` * alongside the `{ sqlType, value? }` pair. Mapped to a kernel * `TypedValue` via the same [`parse_typed_value`] codec and bound with * `StatementSpec::param_named`. Named is the SEA-spec-required public * param form (`StatementParameter.name` is `openapi_required`); * positional is the documented-undocumented variant. The two are * mutually exclusive at the SQL level (`?` vs `:name`). */ namedParams?: Array } /** * A named bound parameter — a [`TypedValueInput`] plus its `:name`. Kept a * distinct napi object (rather than an optional `name` on `TypedValueInput`) * so the positional surface stays a clean ordered list with no name field. */ export interface NamedTypedValueInput { name: string sqlType: string value?: string } /** * Authentication mode selector crossing the napi boundary. The string * literals are what napi-rs emits from this `#[napi(string_enum)]` — the * NodeJS SEA adapter (`KernelAuth`) matches them verbatim (`'Pat'`, * `'OAuthM2m'`, `'OAuthU2m'`). * * Mirrors the kernel [`AuthConfig`] variants this binding supports. * `OAuthFederation` / `External` are intentionally not exposed yet — the * kernel marks federation as not-yet-implemented and `External` is a * Rust-trait escape hatch with no JS-callback bridge. */ export const enum AuthMode { /** Personal access token (`token`). */ Pat = 'Pat', /** OAuth 2.0 machine-to-machine — `oauthClientId` + `oauthClientSecret`. */ OAuthM2m = 'OAuthM2m', /** * OAuth 2.0 user-to-machine (browser flow) — optional `oauthClientId` * + `oauthRedirectPort`. */ OAuthU2m = 'OAuthU2m' } /** * A single extra HTTP header as an explicit `{ name, value }` pair. * * An ordered list of these (`ConnectionOptions.custom_headers`) mirrors * the kernel core's `Vec<(String, String)>` and the pyo3 binding's * `http_headers`: order is preserved and duplicate `name`s are allowed. * A struct (rather than a raw `[name, value]` tuple) because napi-rs * does not marshal Rust tuples through `#[napi(object)]` fields; the * struct is the idiomatic, self-documenting equivalent and maps to a JS * `{ name: string, value: string }`. */ export interface HeaderEntry { name: string value: string } /** * Programmatic HTTP/HTTPS proxy configuration, mirroring the kernel's * internal [`ProxyConfig`]. Supplied as a structured object rather than a * flattened URL so credentials never have to be percent-encoded into the URL * and the bypass-host list can be expressed. * * - `url` — proxy endpoint, e.g. `"http://proxy.corp.example.com:8080"`. Must * use the `http://` or `https://` scheme. * - `username` / `password` — optional proxy basic-auth, applied via * `reqwest`'s `Proxy::basic_auth` (not embedded in the URL). * - `bypassHosts` — optional comma-separated host/domain list that should * bypass the proxy (e.g. `"localhost,*.internal.corp"`). */ export interface ProxyInput { url: string username?: string password?: string bypassHosts?: string } /** * JS-visible options for opening a Databricks SQL session. * * Authentication is selected by `authMode` (default [`AuthMode::Pat`]): * - `Pat` — `token` required. * - `OAuthM2m` — `oauthClientId` + `oauthClientSecret` required. * - `OAuthU2m` — `oauthClientId` / `oauthRedirectPort` optional * (defaults to the `databricks-sql-connector` client on port 8020). * * Catalog / schema / sessionConf are applied once at session creation * and remain in effect for every statement run on the resulting * `Connection`. The SEA wire protocol carries them on * `CreateSession`, not on `ExecuteStatement` — so there is no * per-statement override path on this binding. */ export interface ConnectionOptions { /** * Workspace host, e.g. `adb-…azuredatabricks.net`. The kernel * normalises this — bare hostnames get `https://` prepended. */ hostName: string /** * JDBC-style HTTP path, e.g. `/sql/1.0/warehouses/abc123`. The * kernel parses out the warehouse id. */ httpPath: string /** * Authentication mode. Omitted ⇒ [`AuthMode::Pat`] (back-compat: * existing PAT callers pass only `token`). */ authMode?: AuthMode /** * Personal access token. Required (and non-empty) for * [`AuthMode::Pat`]; ignored otherwise. */ token?: string /** * OAuth client id. Required for [`AuthMode::OAuthM2m`]; optional for * [`AuthMode::OAuthU2m`] (defaults to `databricks-sql-connector`). */ oauthClientId?: string /** OAuth client secret. Required for [`AuthMode::OAuthM2m`]. */ oauthClientSecret?: string /** * Localhost callback port for the [`AuthMode::OAuthU2m`] browser * flow. Omitted ⇒ kernel default (8020). */ oauthRedirectPort?: number /** * OAuth scopes override (M2M / U2M). Omitted ⇒ kernel defaults * (`["all-apis"]` for M2M; `["all-apis", "offline_access"]` for U2M). */ oauthScopes?: Array /** * Default catalog for statements executed on this session. * Routed through the kernel's `DefaultOpts` and onto the SEA * `CreateSession.catalog` wire field. */ catalog?: string /** * Default schema for statements executed on this session. * Routed through the kernel's `DefaultOpts` and onto the SEA * `CreateSession.schema` wire field. */ schema?: string /** * Server-bound session conf (Spark conf, `ANSI_MODE`, `TIMEZONE`, * query-tag presets, …). Forwarded verbatim to SEA * `session_confs`. Unknown keys are rejected server-side. */ sessionConf?: Record /** * Maximum number of pooled HTTP connections per host. Routes * through the kernel's [`HttpConfig::pool_max_idle_per_host`]. * Tunes the underlying `reqwest` connection pool — higher values * reduce reconnect overhead when many statements run * concurrently against the same warehouse. * * When the JS caller does NOT provide `maxConnections`, the napi * binding applies a NodeJS-driver-appropriate default of * [`NAPI_DEFAULT_POOL_MAX_IDLE_PER_HOST`] (100) — chosen to match * the JDBC driver's `HttpConnectionPoolSize` default and to close * the throughput gap vs the NodeJS Thrift driver's * `maxSockets: Infinity` pool for bursty workloads. The kernel * core's [`HttpConfig::pool_max_idle_per_host`] default is also 100 * (matching the same JDBC default), so napi pins its own copy rather * than inheriting it. Mirrors the Python connector's * `max_connections` kwarg on the SEA backend, which exposes the * knob but keeps its own urllib3-aligned default of 10. * * Napi-rs serialises `u32` as JS `number`; values up to * `2^32 - 1` round-trip safely (any reasonable pool size fits). */ maxConnections?: number /** * Render `INTERVAL` / `DURATION` result columns as strings * (`ResultConfig.intervals_as_string`). The kernel default is * native Arrow `month_interval` / `duration[us]` types; the NodeJS * Thrift driver surfaces intervals as strings, so the SEA driver * sets this `true` for byte-compatible parity. Omitted ⇒ kernel * default (native Arrow interval types). */ intervalsAsString?: boolean /** * Render complex (`ARRAY` / `MAP` / `STRUCT` / `VARIANT`) result * columns as JSON strings (`ResultConfig.complex_types_as_json`) * instead of native Arrow nested types. Omitted ⇒ kernel default * (native Arrow nested types, which the NodeJS Arrow decoder * already renders identically to the Thrift path). */ complexTypesAsJson?: boolean /** * Whether to verify the server's TLS certificate. * * Omitted / `true` ⇒ strict validation against the system / Mozilla * trust store (full chain + expiry + hostname), matching JDBC / ODBC * and every modern HTTPS client. This is the **default** for the SEA * backend — secure by default. * * `false` ⇒ permissive: accept self-signed / untrusted / expired * certs AND skip the hostname-vs-SNI check. This is **insecure** (no * protection against active MITM); it exists only as an opt-out for * parity with the legacy NodeJS Thrift driver, which hard-codes * `rejectUnauthorized: false`. Prefer pairing strict checking with * `custom_ca_cert` over disabling verification entirely. * * This is the master verify toggle: `false` disables chain validation * (`TlsConfig::accept_self_signed`) **and** subsumes the hostname * check (`skip_hostname_verification`), regardless of * `check_server_certificate_hostname`. */ checkServerCertificate?: boolean /** * Whether to verify that the server certificate matches the host * (hostname-vs-SNI check), **independently** of full chain validation. * * Omitted / `true` ⇒ the hostname check runs (the secure default). * `false` ⇒ skip only the hostname check while still validating the * chain + expiry against the trust store — for connecting via an IP * literal or a host the cert wasn't issued for, without dropping all * validation. Ignored (already implied) when * `check_server_certificate` is `false`, which disables everything. * * Mirrors the Python connector's `_tls_verify_hostname` knob and the * kernel's [`TlsConfig::skip_hostname_verification`] (= `!check`). */ checkServerCertificateHostname?: boolean /** * PEM-encoded CA certificate bytes to add to the trust store on * top of the system roots. Use for corporate TLS-inspecting * proxies that re-sign TLS, or on-prem deployments with an * internal CA. Honoured regardless of `check_server_certificate`. * Maps onto the kernel [`TlsConfig::custom_ca_cert`]. */ customCaCert?: Buffer /** * PEM-encoded client certificate for mutual TLS (mTLS). Set this * together with `client_key_pem` when the server requires the * client to present a certificate. A PEM carrying a leaf cert * optionally followed by its intermediate chain is accepted. * Maps onto the kernel [`TlsConfig::client_cert_pem`]. * * `client_cert_pem` and `client_key_pem` must be supplied together; * the kernel rejects setting only one at `open_session` with * `InvalidArgument`. */ clientCertPem?: Buffer /** * PEM-encoded private key for the mTLS client certificate. Set this * together with `client_cert_pem`. For portability across the * kernel's TLS backends supply a PKCS#8 key (`BEGIN PRIVATE KEY`). * Maps onto the kernel [`TlsConfig::client_key_pem`]. */ clientKeyPem?: Buffer /** * Extra HTTP headers to send on every request — the route for * caller-supplied headers (the NodeJS driver's `customHeaders` and * the composed `User-Agent`). Maps onto the kernel * [`HttpConfig::custom_headers`]. * * An **ordered list** of `(name, value)` pairs, mirroring the kernel * core's `Vec<(String, String)>` and the pyo3 binding's * `http_headers` — order is preserved and duplicate names are * allowed (the kernel emits each entry, and for `User-Agent` folds * the **last** one into its base UA). * * Three names are handled specially by the kernel: * - `Authorization` / `x-databricks-org-id` are **reserved** — a * caller entry for either is silently dropped (skip-and-warn) so * auth and multi-tenant routing can't be hijacked by a custom * header. (The NodeJS driver also drops these before they cross * the FFI, matching the Python connector's double-wall.) * - `User-Agent` is **appended** to the kernel base UA (rather than * replacing it), preserving the `DatabricksJDBCDriverOSS/...` * token the SEA server keys on while still surfacing the caller's * identity. The NodeJS driver folds its `userAgentEntry` into a * `User-Agent` entry here. */ customHeaders?: Array /** * Retry/backoff tuning — all optional. An unset field keeps the kernel's * built-in policy (1s/60s exponential backoff, 6 total attempts, 900s * budget). Mirrors the pyo3 binding's `retry_*` kwargs so the Node.js * driver can forward the same retry knobs the Python connector does. * * Lower bound of the exponential backoff (also clamps a server * `Retry-After`). Maps onto [`HttpConfig::retry_min_wait`]. */ retryMinWaitSecs?: number /** * Upper bound of the exponential backoff. Maps onto * [`HttpConfig::retry_max_wait`]. */ retryMaxWaitSecs?: number /** * **Total** number of attempts (matching the connector's * `_retry_stop_after_attempts_count` and JDBC count semantics). The * kernel's [`HttpConfig::retry_max_retries`] counts retries *after* the * first attempt, so this is converted with `max(0, attempts - 1)` in * [`build_http_config`] — `0` / `1` both mean a single attempt, no retry. */ retryMaxAttempts?: number /** * Overall retry budget in whole seconds. Maps onto * [`HttpConfig::overall_timeout`]. */ retryOverallTimeoutSecs?: number /** * Programmatic HTTP/HTTPS proxy ([`ProxyInput`]) to route all kernel * traffic through. Carries the proxy `url`, optional basic-auth * `username` / `password`, and an optional `bypassHosts` list — mapped * field-for-field onto the kernel [`ProxyConfig`]. * * Omitted ⇒ the kernel does NOT configure a proxy explicitly and * `reqwest`'s standard behaviour applies — the `HTTPS_PROXY` / * `HTTP_PROXY` / `NO_PROXY` environment variables are still honoured. * Setting this **overrides** those env vars. This complements the env-var * path: callers who cannot set process env vars (e.g. a long-lived Node * server) can now route a single connection through a proxy * programmatically. */ proxy?: ProxyInput /** * Per-connection socket read timeout, in milliseconds. Caps how * long a single HTTP round-trip may block waiting on the server * before the request errors out. Maps onto the kernel * [`HttpConfig::request_timeout`] (the internal reqwest * `Client::timeout`). * * Omitted ⇒ kernel default (120 000 ms / 120 s). Napi-rs * serialises `u32` as JS `number`; the largest representable value * (~49.7 days) far exceeds any sensible socket timeout. */ socketTimeoutMs?: number } /** * Open a Databricks SQL session and return an opaque `Connection` * wrapping the kernel `Session`. Authentication is selected by * `options.auth_mode` (PAT / OAuth M2M / OAuth U2M) — see * [`build_auth_config`]. * * The JS-visible name is `openSession` (napi-rs converts snake_case * to camelCase for free functions). */ export declare function openSession(options: ConnectionOptions): Promise /** * One kernel log event, as handed to JS. `level` is a lower-case string * (`error`/`warn`/`info`/`debug`/`trace`) the Node side maps onto its * `LogLevel`; `target` is the originating `tracing` target (e.g. * `databricks::sql::kernel`); `message` is the rendered event plus any * structured `key=value` fields. */ export interface LogRecord { level: string target: string message: string } /** * Install (idempotently) the kernel→JS log bridge and set its level. * * `callback` is invoked with **an array of [`LogRecord`]s** (`(err, records)`) * for each forwarded batch. `level` is one of * `off`/`error`/`warn`/`info`/`debug`/`trace` (case-insensitive); unknown * values fall back to `warn`. * * Safe to call more than once: the process-global subscriber is installed on * the first call only, while every call refreshes the sink + level (last * writer wins — see module docs). */ export declare function initKernelLogging(callback: (err: Error | null, arg: Array) => any, level: string): void /** * Snapshot of the bridge's runtime state for observability. * * `installed` is `true` only when the process-global subscriber was * successfully installed by *this* bridge (and the drain thread started); * `false` means another global subscriber was already set or the drain * thread could not be spawned, so kernel logs are NOT reaching the JS sink. * `dropped` is the cumulative count of records discarded because the * bounded channel was full during a burst (drop-newest) — a nonzero, * growing value signals the sink can't keep up. */ export interface KernelLoggingStats { installed: boolean dropped: number } /** * Return the bridge's [`KernelLoggingStats`]. Safe to call before * `initKernelLogging` (reports `installed: false`, `dropped: 0`). */ export declare function kernelLoggingStats(): KernelLoggingStats /** * Live-retarget the bridge's level (one of * `off`/`error`/`warn`/`info`/`debug`/`trace`, case-insensitive). */ export declare function setKernelLogLevel(level: string): void /** * JS-visible binding for a single positional parameter. * * Shape mirrors the `TSparkParameter` wire object the Thrift backend * already emits via `DBSQLParameter.toSparkParameter()` — `type` is the * canonical Databricks SQL type name (`"INT"`, `"STRING"`, * `"DECIMAL(10,2)"`, ...), `value` is the string-encoded literal or * `None` for SQL NULL. * * Why a string for `value` instead of a tagged JS union: round-tripping * arbitrary JS values across the FFI requires either (a) a custom * napi `FromNapiValue` per arm, or (b) a `serde_json::Value`-style * dynamic dispatch on the Rust side. The Node-driver adapter already * stringifies before calling the binding (see `DBSQLParameter` and the * existing pyo3 wrapper), so the string-in / string-parsed contract * adds no JS-side complexity and keeps the kernel-side validation in * one place. */ export interface TypedValueInput { /** * Canonical Databricks SQL type name. Case-insensitive for the * simple variants; for DECIMAL the parenthesised form * (`"DECIMAL(10,2)"`) is required so the kernel can extract * precision/scale. */ sqlType: string /** * String-encoded value. `None` always produces `TypedValue::Null` * regardless of `sql_type` — matches the connector's * `VoidParameter` shape and the pyo3 binding's contract. */ value?: string } /** * A single Arrow IPC stream payload encoding one record batch (plus * the schema header so the JS-side reader is stateless). */ export interface ArrowBatch { /** * Arrow IPC stream payload (schema header + 1 record-batch * message). Decode with `apache-arrow`'s `RecordBatchReader`. */ ipcBytes: Buffer } /** * An Arrow IPC stream payload encoding just the result schema (no * record-batch messages). Returned by `Statement.schema()`. */ export interface ArrowSchema { /** * Arrow IPC stream payload (schema header only, no record-batch * messages). Decode with `apache-arrow`'s `RecordBatchReader` — * the reader will expose the schema and immediately end. */ ipcBytes: Buffer } /** * Returns the native binding's crate version (`CARGO_PKG_VERSION`). * * Originally the round-1b smoke test; kept as a cheap "is the binding * loaded?" probe for the JS-side loader's structured diagnostics. */ export declare function version(): string /** * Opaque async-statement handle. * * Returned by `Connection.submitStatement(...)` after the kernel * `Statement::submit()` returns (server sent `wait_timeout=0s`, so * the response carries a `statement_id` but the statement is still * `Pending`/`Running`). JS drives polling via `status()` / * `awaitResult()`. * * Concurrency shape: `status()`, `awaitResult()`, and `close()` take * `inner.lock()` and hold the guard across the kernel `.await` (tokio * `Mutex` is FIFO), so `status()` / `close()` queue behind any * in-flight `awaitResult()` until it returns naturally. `cancel()` is * the deliberate exception: it does **not** touch `inner` — it fires * through the detached `AsyncStatementCanceller` (session + * statement_id, captured at construction), so an explicit * `stmt.cancel()` interrupts an in-flight `awaitResult()` instead of * queueing behind it. The server-side cancel flips the statement * terminal, which the parked `awaitResult()` poll loop observes * (`Cancelled`) and returns on. The kernel's `AwaitResultCancelGuard` * still covers the drop-cancel case (Promise.race / timeout) * independently — see module docs. */ export declare class AsyncStatement { /** * Server-issued statement id. Cached at construction; readable * even after `close()` so JS-side log lines can correlate * against kernel / server logs which key on the same id. */ get statementId(): string /** * One-shot status check. Returns a string enum matching the * kernel `StatementStatus` shape: * `'Pending' | 'Running' | 'Succeeded' | 'Failed' | * 'Cancelled' | 'Closed' | 'Unknown'`. (`'Unknown'` is the * `#[non_exhaustive]` forward-compat catch-all that * `StatementStatus::as_str` can return — consumers switching on * the state must handle it.) Returns * `KernelError(InvalidStatementHandle)` if the statement has * been explicitly `close()`d. * * The `Failed` variant collapses to the string `'Failed'` on * the JS side; the underlying error envelope (sql_state / * error_code / query_id) is surfaced by `awaitResult()`'s * rejection, which is where callers actually need the typed * error. `status()` is intended for polling progress UIs * that only need the state name. */ status(): Promise /** Rows modified by the statement (UPDATE / INSERT / DELETE / MERGE). */ numModifiedRows(): Promise /** * Server-supplied user-facing message (may contain SQL fragments — * redact before centralised logging). */ displayMessage(): Promise /** Server-supplied diagnostic detail. */ diagnosticInfo(): Promise /** Server-supplied structured error detail (JSON), when enabled. */ errorDetailsJson(): Promise /** * Block until the server reaches a terminal state, then return * an `AsyncResultHandle` that wraps the materialised result * stream. The handle exposes `fetchNextBatch()` / `schema()` * for consuming the result, plus `statementId` for log * correlation. * * Drop-cancel safety: kernel `await_result` installs * `AwaitResultCancelGuard` which fires a fire-and-forget * `cancel_statement` if the future is dropped mid-poll * (timeout, tokio::select! loser, JS-side `Promise.race` * loser). The `util::guarded` `catch_unwind` here covers the * V8-panic-across-boundary case on top. Returns * `KernelError(InvalidStatementHandle)` if the statement has * been explicitly `close()`d. */ awaitResult(): Promise /** * Server-side cancel. Returns * `KernelError(InvalidStatementHandle)` if the statement has * been explicitly `close()`d. Idempotent against a server * that already reached a terminal state — the kernel's * `cancel_statement` is a no-op there. * * **Lock-free by design.** Unlike `status()` / `awaitResult()` / * `close()`, this does not take `inner.lock()` — it fires through * the detached `AsyncStatementCanceller` captured at construction. * That lets `stmt.cancel()` interrupt an in-flight `awaitResult()` * (which holds the mutex for the whole poll) instead of queueing * behind it: the server-side cancel flips the statement terminal, * the parked `awaitResult()` poll loop observes `Cancelled` and * returns. The closed-state check reads a lock-free flag so a * cancel after an explicit `close()` still surfaces * `InvalidStatementHandle`. */ cancel(): Promise /** * Explicit close. Idempotent — a second call on an * already-closed handle returns `Ok(())`. On `Err`, the napi * inner is already `None`, so a JS-side retry sees the * closed-handle short-circuit and returns `Ok(())` without * re-attempting the wire call. The kernel's own `Drop` * fire-and-forget retry runs once in the background. */ close(): Promise } /** * Opaque result-fetch handle returned by * `AsyncStatement.awaitResult()`. Wraps a kernel `ResultStream` * directly; structurally analogous to the sync `Statement`'s * fetch-side surface (`fetchNextBatch` / `schema` / * `statementId`). * * `cancel()` / `close()` are not exposed: the parent * `AsyncStatement` owns server-side lifecycle. A `close()` here * would create dual-ownership of the same statement_id with * inconsistent close semantics. Callers `close()` the parent * `AsyncStatement` after they're done fetching. * * Schema is cached at construction so it survives the underlying * stream being drained; mirrors the sync `Statement.schema()` * post-close contract. */ export declare class AsyncResultHandle { /** * Server-issued statement id. Cached at construction; readable * for log correlation. Matches the parent `AsyncStatement`'s * `statementId`. */ get statementId(): string /** * Pull the next batch of results. Returns `null` when the * stream is exhausted. The returned `ArrowBatch.ipcBytes` is a * complete Arrow IPC stream (schema header + 1 record-batch * message), suitable for handing to `apache-arrow`'s * `RecordBatchReader`. Byte-identical to the sync * `Statement.fetchNextBatch()` payload for the same query. */ fetchNextBatch(): Promise /** * Result schema as an Arrow IPC payload (schema header only, * no record-batch message). Available before any batches have * been fetched. Sync because the body has no `.await` — * `encode_ipc_stream` is pure CPU work over the cached * `Arc`. */ schema(): ArrowSchema } /** * Handle returned by `Connection.executeStatementCancellable`. Owns the * built-but-not-yet-executed kernel `Statement` plus a detached * [`StatementCanceller`] captured before dispatch, so JS can fire a * server-side cancel while the blocking `result()` is in flight. * * `pending` is `Arc>>` so `result()` can * `.take()` the statement (the kernel `execute()` borrows it `&mut`, * then it moves into the produced `Statement` wrapper to keep its * `ValidityFlag` set — see `statement.rs`). A second `result()` call * after the first resolved surfaces `InvalidStatementHandle`. */ export declare class CancellableExecution { /** * The server-issued statement id this execution targets, if the * server has issued one yet (`null` before the initial submit * round-trip publishes it mid-`result()`). Useful for log * correlation while the blocking drive is in flight. */ get statementId(): string | null /** * Drive the blocking `execute()` and resolve to a `Statement` * (identical to what `executeStatement` returns) once the kernel * reaches a terminal state and the result stream is ready. * * Consumes the pending statement: a second `result()` call returns * `KernelError(InvalidStatementHandle)`. The future is * drop-cancel-safe — the kernel's per-execute `MidExecuteCancelState` * guard fires a fire-and-forget `cancel_statement` if this future is * dropped mid-flight (`Promise.race` / timeout loser), independently * of an explicit `cancel()`. * * On a server-side cancel the kernel's blocking `execute()` currently * surfaces `InvalidArgument` (a known kernel quirk — the async path * returns `Cancelled`). When this handle's `cancel()` actually dispatched a * server-side cancel, we normalise that into `Cancelled` here so JS callers * can rely on a single cancelled-status code regardless of execution path. * * Three outcomes can race the blocking drive: (1) a natural terminal state * → `Ok` or the genuine error; (2) an explicit `cancel()` that dispatched a * server cancel → this `result()` rejects with a `Cancelled`-coded error * (the normalisation above); (3) the future being **dropped** mid-flight * (`Promise.race`/timeout loser) → the kernel's `MidExecuteCancelState` * drop-guard fires a fire-and-forget `cancel_statement`, but there is no * `result()` left to observe a code. Only (2) yields a `Cancelled` error. */ result(): Promise /** * Server-side cancel of the in-flight statement. * * Lock-free: fires the detached `StatementCanceller` captured at * construction rather than taking the mutex `result()` holds, so it * interrupts a still-running blocking `result()` instead of queueing * behind it. No-op (returns `Ok`) if `result()` already finished * successfully, or if no statement id has been observed yet (query still * in its initial submit round-trip), and idempotent against a server * already in a terminal state. */ cancel(): Promise } /** * Opaque connection handle wrapping a kernel `Session`. * * `inner` is `Arc>>` so: * - the Drop impl can clone the `Arc` and `.take()` the session on a * background tokio task without holding `&mut self` (which Drop is * forbidden from doing across an `await`), * - `close()` can `.take()` the session to consume it for the kernel's * move-by-value `Session::close(self)` signature. * * **Concurrency shape** — both `executeStatement` and * `submitStatement` build the kernel `Statement` under `inner.lock()` * and then RELEASE the guard before the wire call * (`stmt.execute().await` / `stmt.submit().await`). `Session::statement()` * is `&self`-callable and only clones the session's internal `Arc`, so * the built statement is independent of the guard. Concurrent * `Promise.all([executeStatement(q1), submitStatement(q2)])` therefore * serialise only for the microsecond statement-build, not the network * round-trip, and `close()` never blocks behind an in-flight execute or * submit. See * `sea-workflow/jira-candidates/2026-05-24-napi-cancel-during-fetch.md`. */ export declare class Connection { /** * Server-issued session id. Cached at construction; readable * even after `close()` so JS-side log lines can correlate * against kernel / server logs which key on the same id. */ get sessionId(): string /** * Execute a SQL statement and return a Statement handle that * streams batches via `fetchNextBatch()`. * * Catalog / schema / sessionConf are session-level * (`openSession`). Per-statement options on `ExecuteOptions`: * - `statementConf` — per-statement Spark conf overlay * - `queryTags` — serialised to a comma-separated `key:value` * string and placed in `statement_conf["query_tags"]`, * matching NodeJS Thrift's `serializeQueryTags` wire shape * * `options` is omitted/`None` for the no-options path; passing * `{ statementConf: {} }` (an empty map) is treated the same as * omission to keep the wire shape stable for the common case. */ executeStatement(sql: string, options?: ExecuteOptions | undefined | null): Promise /** * directResults execute — the Thrift/JDBC model. Sends ExecuteStatement * with no `wait_timeout` field (server applies its ~10s default inline wait * and auto-closes on success) and returns WITHOUT polling past it: * * - a **`Statement`** (left arm) when the query finished within the inline * wait — terminal, result ready inline, `close()` is a clean release; * - an **`AsyncStatement`** (right arm) when it did not — a poll/cancel * handle the caller drives (`status()` / `awaitResult()` / `cancel()`). * * JS distinguishes the arms by feature-detecting `awaitResult` (present * only on `AsyncStatement`). This is the path that gives mid-run cancel for * long queries WITHOUT the eager-handle / close-drives workaround: the * returned handle always corresponds to a server-owned statement. * * **Load-bearing contract:** the kernel's `DirectStatement::{Completed, * Running}` discriminant cannot ride on these opaque `#[napi]` classes, so * consumers MUST feature-detect via `awaitResult` (the only member unique to * `AsyncStatement`). `Statement` (the Completed arm) MUST NOT gain an * `awaitResult` member, or every consumer silently misroutes. The pyo3 * binding makes the same `await_result`-probe assumption. */ executeStatementDirect(sql: string, options?: ExecuteOptions | undefined | null): Promise /** * Execute a SQL statement on the blocking (sync) path, but return a * `CancellableExecution` handle so a concurrent JS task can cancel * the query *while it is still running server-side*. * * `executeStatement` builds the kernel `Statement`, awaits the * blocking `execute()`, and only then hands JS a `Statement` — so a * query that runs for several seconds is uncancellable from JS on * that path (there is no handle until the blocking call resolves). * This method instead builds the statement, captures a detached * `StatementCanceller` **before** dispatching `execute()`, and hands * JS a `CancellableExecution` immediately. The caller drives the * blocking execution via `result()` (resolves to the same * `Statement` `executeStatement` returns) and can fire `cancel()` * concurrently to interrupt a still-running query mid-COMPUTE. * * Option semantics are identical to `executeStatement`. * Mirrors the pyo3 `Statement.canceller()` / `Statement.execute()` * split (PR #121): obtain the canceller before the blocking drive. */ executeStatementCancellable(sql: string, options?: ExecuteOptions | undefined | null): Promise /** * Submit a SQL statement and return immediately with an * `AsyncStatement` handle, without blocking until the query * finishes. The kernel's `Statement::submit()` sends * `wait_timeout=0s`, so the server responds as soon as it has a * `statement_id` (state `Pending`/`Running`); JS drives polling * via `AsyncStatement.status()` and materialises results with * `AsyncStatement.awaitResult()`. * * This is the async-execution path the Thrift backend always * uses (`runAsync: true`): the SEA backend submits, returns a * pending operation handle, and polls to terminal during * fetch. Option semantics (statementConf / queryTags / * rowLimit / positional + named params) match `executeStatement`. * Submit always sends `wait_timeout=0s` so the call returns * immediately; the caller drives completion via `status()` / * `awaitResult()`. Only the blocking-vs-pending return contract * differs from `executeStatement`. */ submitStatement(sql: string, options?: ExecuteOptions | undefined | null): Promise /** * Explicit close. Awaits the server-side `DeleteSession` so the * JS caller can observe failures (auth revoked mid-session, * warehouse stopped, network error). Idempotent — a second call * on an already-closed connection returns `Ok`. * * **Errors are terminal from the JS side.** The kernel session * handle is consumed (`take()`) BEFORE the wire `DeleteSession` * runs, because `Session::close` takes `self` by value. On `Err`, * the napi `inner` is already `None`, so a JS-side retry sees a * closed connection and returns `Ok(())` without re-attempting * the wire call. The kernel's own `Drop` fire-and-forget retry * runs once in the background — the JS caller can log the error * but cannot drive a retry. If you need retry-on-failure * semantics for `DeleteSession`, layer them above this method. */ close(): Promise /** * All catalogs visible to the session. * * JDBC `getCatalogs` shape: `TABLE_CAT: Utf8`. */ listCatalogs(): Promise /** * Schemas filtered by catalog (exact) and schema name pattern. * * JDBC `getSchemas` shape: `TABLE_SCHEM, TABLE_CATALOG`. */ listSchemas(catalog?: string | undefined | null, schemaPattern?: string | undefined | null): Promise /** * Tables filtered by catalog (exact), schema (pattern), table (pattern). * * JDBC `getTables` shape: 10 columns. `tableTypes`, when provided, * filters rows by `TABLE_TYPE` kernel-side. * * `tableTypes` is an advisory filter. Databricks `SHOW TABLES` does * NOT honour the table-type filter server-side; the kernel applies * it client-side after the result returns. Callers expecting * server-side rejection of off-type tables should not rely on this. */ listTables(catalog?: string | undefined | null, schemaPattern?: string | undefined | null, tablePattern?: string | undefined | null, tableTypes?: Array | undefined | null): Promise /** * Columns of tables matching the filter. * * JDBC `getColumns` shape: 23 columns. */ listColumns(catalog?: string | undefined | null, schemaPattern?: string | undefined | null, tablePattern?: string | undefined | null, columnPattern?: string | undefined | null): Promise /** * Functions visible to the session. `catalog` is exact; * `schemaPattern` and `functionPattern` are SQL LIKE. */ listFunctions(catalog?: string | undefined | null, schemaPattern?: string | undefined | null, functionPattern?: string | undefined | null): Promise /** * Procedures visible to the session. `catalog` is exact; * `schemaPattern` and `procedurePattern` are SQL LIKE. */ listProcedures(catalog?: string | undefined | null, schemaPattern?: string | undefined | null, procedurePattern?: string | undefined | null): Promise /** * All table types (`TABLE`, `VIEW`, `SYSTEM TABLE`, …). * No wire call — static in-memory result. */ listTableTypes(): Promise /** * SQL data types supported by the workspace. * No wire call — static in-memory result. */ listTypeInfo(): Promise /** * Primary keys for the given table. All three identifiers are * exact — ODBC `SQLPrimaryKeys` does not support patterns. */ getPrimaryKeys(catalog: string, schema: string, table: string): Promise /** * Foreign-key relationships. The foreign side must be fully * specified (catalog + schema + table); the parent side is * optional. All identifiers are exact — no LIKE patterns. */ getCrossReference(parentCatalog: string | undefined | null, parentSchema: string | undefined | null, parentTable: string | undefined | null, foreignCatalog: string, foreignSchema: string, foreignTable: string): Promise } /** * Opaque executed-statement handle. * * **Current concurrency shape** — every method takes `inner.lock()` * and holds the guard across the kernel `.await`. tokio `Mutex` is * FIFO, so cancel/close queue behind any in-flight `fetchNextBatch` * until it returns naturally. This is a known limitation that exists * because the napi shape has not yet been split into an * `Arc` (for cancel/close, which the * kernel exposes as `&self`-callable) plus a `Mutex>` only * for the borrowed-mut fetch path. The lock-shape refactor needs a * small kernel-side accessor and lands in a follow-up PR — see * `sea-workflow/jira-candidates/2026-05-24-napi-cancel-during-fetch.md`. * * `schema` and `statement_id` are cached at construction so they * survive `close()` — JS callers building error reports against a * disposed statement can still read them. */ export declare class Statement { /** * Server-issued statement id. Cached at construction; readable * even after `close()` so JS-side log lines can correlate against * kernel / server logs which key on the same id. */ get statementId(): string /** * Number of rows modified by the statement (UPDATE / INSERT / * DELETE / MERGE). `null` for SELECT and on warehouses that don't * surface the counter. Mirrors Thrift's * `TGetOperationStatusResp.numModifiedRows`. */ numModifiedRows(): Promise /** * Server-supplied user-facing message. Mirrors Thrift's * `TGetOperationStatusResp.displayMessage`. **PII / sensitive- * data note:** may contain SQL fragments or parameter values — * redact before centralised logging. * * Populated on `Succeeded` / `Closed` paths (incl. an empty `Closed`). * On terminal-error states (`Failed` / `Cancelled`) the kernel returns * an Error instead of a `Statement`, and the same field rides on the JS * Error envelope under the same `displayMessage` key. */ displayMessage(): Promise /** * Server-supplied diagnostic detail — multi-line operator / * stack context. Mirrors Thrift's * `TGetOperationStatusResp.diagnosticInfo`. For support surfaces, * not user-facing. Same reachability + PII caveats as * `displayMessage`. */ diagnosticInfo(): Promise /** * Server-supplied JSON blob with extended error details. Mirrors * Thrift's `TGetOperationStatusResp.errorDetailsJson`. * Pass-through string — JS callers parse with `JSON.parse` if * they need structured access. * * **Server-side gating:** populated only when the workspace has * `spark.databricks.sql.errorDetailsJson.enabled = true` on the * underlying SQL cluster. The flag is internal-only / default- * false in the Databricks runtime, so for most JS callers this * will return `null`. Admin-enabled workspaces return content * shaped like `{"errorClass": "...", "messageTemplate": "..."}`. * * **Unbounded:** when populated, server can return a multi-MB * blob; size before logging. */ errorDetailsJson(): Promise /** * Pull the next batch of results. Returns `null` when the stream * is exhausted. The returned `ArrowBatch.ipcBytes` is a complete * Arrow IPC stream (schema header + 1 record-batch message) * suitable for handing to `apache-arrow`'s `RecordBatchReader`. * * On `Err`, the stream is in an unspecified state — call * `close()` and discard the `Statement`. Subsequent * `fetchNextBatch()` calls after an error are not guaranteed to * succeed or fail consistently. */ fetchNextBatch(): Promise /** * Result schema as an Arrow IPC payload (schema header only, no * record-batch message). Available before any batches have been * fetched, and remains available after `close()` — the kernel * materialises the schema eagerly so JS callers can build error * reports against a disposed statement. * * Sync because the body has no `.await` — `encode_ipc_stream` is * pure CPU work over an `Arc` already cached on the * wrapper. Mirrors `pyo3/src/statement.rs::arrow_schema` (sync). * napi-rs converts a panic in a sync `#[napi]` entry point into a * thrown JS error via its own macro-expanded boundary, so the * `util::guarded` `catch_unwind` wrapper that the `async fn` * entry points use is not required for this method. */ schema(): ArrowSchema /** * Server-side cancel. * * For executed statements: short-circuits to `Ok(())` if * `fetchNextBatch` has already returned `null` (stream * naturally exhausted) — matches the JDBC `Statement.cancel()` * no-op-after-completion contract, so JS callers can fire cancel * defensively without distinguishing "real cancel" from "raced * with natural completion." * * For metadata streams: no-op (the kernel has no in-flight * cancellation surface for metadata calls today). * * Returns `KernelError(InvalidStatementHandle)` if the statement * has been explicitly `close()`d. */ cancel(): Promise /** * Explicit close. * * For executed statements: awaits the server-side `CloseStatement` * so the JS caller can observe failures (auth revoked mid-session, * network error, server-side error). Idempotent — a second call * on an already-closed statement returns `Ok`. * * **Errors are terminal from the JS side.** The kernel executed * handle is taken out of `inner` BEFORE the wire `CloseStatement` * runs (so `Drop` knows there's nothing left to clean up). On * `Err`, the napi `inner` is already `None`, so a JS-side retry * sees a closed statement and returns `Ok(())` without re- * attempting the wire call. The kernel-level `ExecutedStatement` * has been consumed at that point and the value is dropped on * the way out of the closure — the kernel's `ExecutedStatement:: * Drop` then fires-and-forgets a single retry on the captured * runtime. The JS caller can log the error but cannot drive a * further retry. If you need retry-on-failure semantics for * `CloseStatement`, layer them above this method. * * For metadata streams: drops the stream (no server round-trip * needed — metadata results have no in-flight server-side * resource to release). */ close(): Promise }