import ISessionBackend from '../contracts/ISessionBackend'; import IOperationBackend from '../contracts/IOperationBackend'; import IClientContext from '../contracts/IClientContext'; import { ExecuteStatementOptions, TypeInfoRequest, CatalogsRequest, SchemasRequest, TablesRequest, TableTypesRequest, ColumnsRequest, FunctionsRequest, PrimaryKeysRequest, CrossReferenceRequest } from '../contracts/IDBSQLSession'; import Status from '../dto/Status'; import InfoValue from '../dto/InfoValue'; import { KernelConnection } from './KernelNativeLoader'; export interface KernelSessionBackendOptions { /** The opaque napi `Connection` handle returned by `openSession`. */ connection: KernelConnection; context: IClientContext; /** Optional override for `id`. Defaults to a fresh UUIDv4. */ id?: string; } export default class KernelSessionBackend implements ISessionBackend { private readonly connection; private readonly context; private readonly _id; private closed; constructor({ connection, context, id }: KernelSessionBackendOptions); get id(): string; /** * `getInfo` (JDBC `DatabaseMetaData` / ODBC `SQLGetInfo`) has no kernel * endpoint, so — exactly as JDBC does for `DatabaseMetaData` — we synthesize * the answer client-side for the three `TGetInfoType`s the Databricks server * answers (server name / DBMS name / DBMS version) and reject the rest. * * This is NOT a kernel-only contract narrowing: probing the live warehouse over * the Thrift path confirms the server itself returns an error for every * other `TGetInfoType` (CLI_MAX_DRIVER_CONNECTIONS, CLI_DATA_SOURCE_NAME, …), * and the three values it does answer are byte-identical to the constants we * synthesize (`"Spark SQL"` / `"Spark SQL"` / `"3.1.1"`, re-verified live). * So rejecting an unsupported type matches Thrift's effective behaviour — we * just surface a clearer, typed error than the server's opaque one. See * {@link kernelServerInfoValue}. */ getInfo(infoType: number): Promise; /** * Execute a SQL statement through the napi binding. * * Catalog / schema / sessionConf are session-level (applied at open). * Per-statement options forwarded to the kernel `ExecuteOptions`: * - `ordinalParameters` / `namedParameters` → bound params (mutually * exclusive — the kernel binds one placeholder style per statement); * - `queryTimeout` → NO-OP on kernel (SQL Warehouses use `STATEMENT_TIMEOUT`); * never forwarded to the kernel and never applied as a client-side * deadline — see the note in `executeStatement`; * - `rowLimit` → `rowLimit` (kernel-only server-side row cap); * - `queryTags` → serialised into the conf overlay's reserved * `query_tags` key (the same wire shape Thrift's `serializeQueryTags` * produces), merged with any explicit `statementConf`. * * Still rejected (genuinely unsupported on kernel, rather than silently * dropped): `useCloudFetch` (governed by the kernel `ResultConfig`, not a * per-statement knob), `useLZ4Compression` (kernel owns result compression), * and `stagingAllowedLocalPath` (volume operations). `maxRows` is applied by * the facade at fetch time, so it is intentionally not handled here. */ executeStatement(statement: string, options: ExecuteStatementOptions): Promise; /** * Translate the public `ExecuteStatementOptions` into the kernel napi * `ExecuteOptions`, returning `undefined` when nothing is set so the * no-options call shape (`executeStatement(sql)`) is preserved. */ private buildExecuteOptions; /** Wrap a napi metadata `Statement` (already terminal) as an operation backend. */ private wrapStatement; /** * Metadata calls forward to the kernel's metadata surface (`listCatalogs`, * `listTables`, …), each of which returns a napi `Statement` whose result * carries the JDBC-shaped columns. We wrap that handle exactly like an * executed statement. The kernel owns the SQL synthesis, the column * projection, and (for `listTables`) the client-side `TABLE_TYPE` filter — * the driver only maps the request fields to positional arguments. * * The `runAsync` / `maxRows` request fields are not threaded here: `runAsync` * is deprecated, and `maxRows` is applied by the facade at fetch time (same * as the Thrift path), so the napi call takes only the filter arguments. */ getTypeInfo(_request: TypeInfoRequest): Promise; getCatalogs(_request: CatalogsRequest): Promise; getSchemas(request: SchemasRequest): Promise; getTables(request: TablesRequest): Promise; getTableTypes(_request: TableTypesRequest): Promise; getColumns(request: ColumnsRequest): Promise; getFunctions(request: FunctionsRequest): Promise; getPrimaryKeys(request: PrimaryKeysRequest): Promise; getCrossReference(request: CrossReferenceRequest): Promise; /** Run a napi metadata call, mapping kernel errors and wrapping the result handle. */ private runMetadata; /** * Map a napi/kernel error to a typed driver error and emit a debug breadcrumb * first, matching the rest of the kernel backend's logging convention * (`KernelOperationLifecycle` / `KernelOperationBackend`). Metadata and bound-param * execute failures otherwise threw with no on-call signal. */ private logAndMapError; close(): Promise; private failIfClosed; }