Repository navigation
feat(remote): add SQL Server data source - #1064
DoubleCore wants to merge 5 commits into
Conversation
4d93315 to
1cc8f89
Compare
Add a read-only Microsoft SQL Server remote engine for AVA. - SqlServerEngine with tedious (production) and in-memory mock adapters - INFORMATION_SCHEMA-based schema discovery (tables, columns, primary keys) - Per-column profile metrics compiled into read-only T-SQL - Read-only SELECT guard, SELECT TOP (N) result caps, maxRows/maxResultBytes - Runtime tedious require so the module has no hard dependency on tedious - Registered for SDK (src/index.ts) and CLI (protocol/datasets/source helpers) - Vitest suite on the mock adapter; docs (site mdx + module README) with two natural-language examples over the seeded sales data Closes antvis#1011
1cc8f89 to
8ca53fa
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical defects allow writes to bypass read-only validation, can crash or hang the process, and break SQL Server connectivity and schema discovery.
18 open issues
Read-only guard permits wrapped write statements · New Reject unmatched closing brackets without hanging · New Serialize catalog queries on the Tedious connection · New Load the optional driver in both module formats · New Handle connection errors to prevent process crashes · New Decode Tedious rows using column aliases · New Preserve CTEs and ordering when applying row limits · New Expose the SQL Server mock seed through a public entry · New Support generated profiling expressions in the mock · New Evaluate HAVING clauses or reject unsupported queries · New Honor SQL AND-before-OR predicate precedence · New Preserve composite primary keys in mock discovery · New Map bit columns as booleans, not numbers · New Preserve time components in timestamp bounds · New Escape all JSON-special characters in profile values · New Cast text, ntext, and xml before profiling · New Filter key metadata to primary-key constraints · New Preserve schema-qualified table identities · New
What changed in this PR
Adds SQL Server as a remote analysis engine in AVA, extending the SDK and CLI toward the schema discovery, read-only querying, and natural-language analysis requested in #1011.
Changes:
- Adds Tedious and in-memory mock adapters, schema discovery, profiling, and connection lifecycle handling.
- Introduces T-SQL generation, validation, result limiting, and SDK/CLI registration.
- Adds mock-based tests, sales seed data, and connection documentation.
| File | Description |
|---|---|
src/types.ts |
Defines SQL Server source options and mock seed types. |
src/remote/sqlserver/tedious.ts |
Implements the optional production driver connector. |
src/remote/sqlserver/tds-config.ts |
Builds connection, authentication, and timeout settings. |
src/remote/sqlserver/schema.ts |
Discovers tables, columns, and key metadata. |
src/remote/sqlserver/README.md |
Documents adapters, setup, examples, and verification. |
src/remote/sqlserver/profile.ts |
Compiles column metrics into aggregate T-SQL. |
src/remote/sqlserver/mock.ts |
Provides seeded catalog views and limited query execution. |
src/remote/sqlserver/index.ts |
Exports engine components and helpers. |
src/remote/sqlserver/examples.ts |
Supplies sales data for examples and tests. |
src/remote/sqlserver/engine.ts |
Connects discovery, profiling, translation, and execution. |
src/remote/sqlserver/connector.ts |
Defines the connector contract and adapter factory. |
src/remote/index.ts |
Exposes the SQL Server engine internally. |
src/query/sqlserver.ts |
Adds T-SQL generation, validation, and row limiting. |
src/index.ts |
Registers the engine and exports configuration types. |
src/engines.ts |
Updates the unavailable-engine error message. |
src/cli/session/protocol.ts |
Validates SQL Server session configuration. |
src/cli/session/datasets.ts |
Selects SQL Server automatically for matching CLI sources. |
src/cli/commands/source.ts |
Updates engine-selection help text. |
site/public/logos/sql-server.svg |
Adds the source-card image asset. |
site/content/docs/en/engines/remote.mdx |
Documents SQL Server within the remote-engine workflow. |
site/content/docs/en/data/sources.mdx |
Adds connection fields, adapter guidance, and examples. |
__tests__/remote/sqlserver.test.ts |
Adds mock-backed engine tests and profiling unit tests. |
Review effort: Balanced
| if (MULTI_STATEMENT.test(` ${stripped}`)) { | ||
| throw new Error('SQL Server query must contain exactly one read-only SELECT statement'); | ||
| } |
| i = j; | ||
| continue; | ||
| } | ||
| if (/[a-zA-Z_@\[\]"]/.test(ch)) { |
| const [columns, keys] = await Promise.all([ | ||
| runQuery(` | ||
| SELECT | ||
| c.TABLE_NAME AS table_name, | ||
| c.COLUMN_NAME AS name, | ||
| c.DATA_TYPE AS type, | ||
| c.IS_NULLABLE AS nullable | ||
| FROM INFORMATION_SCHEMA.COLUMNS c | ||
| WHERE c.TABLE_CATALOG = ${db} | ||
| ORDER BY c.TABLE_NAME, c.ORDINAL_POSITION | ||
| `), | ||
| runQuery(` | ||
| SELECT | ||
| k.TABLE_NAME AS table_name, | ||
| k.COLUMN_NAME AS name, | ||
| k.ORDINAL_POSITION AS position | ||
| FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE k | ||
| WHERE k.TABLE_CATALOG = ${db} | ||
| ORDER BY k.TABLE_NAME, k.ORDINAL_POSITION | ||
| `), | ||
| ]); |
| if (cachedModule !== undefined) return cachedModule; | ||
| try { | ||
| // eslint-disable-next-line @typescript-eslint/no-var-requires | ||
| cachedModule = require('tedious') as TediousModule; |
| const connection = new Connection(config); | ||
|
|
||
| const ok = await new Promise<boolean>((resolve) => { | ||
| connection.connect((error) => resolve(!error)); |
| /** Epoch-milliseconds expression for a date column (86400000 ms per day from SQL Server's epoch). */ | ||
| function epochMs(column: string): string { | ||
| return `(DATEDIFF_BIG(day, '1970-01-01', ${column}) * 86400000.0)`; | ||
| } |
| const value = `CAST(${column!} AS nvarchar(4000))`; | ||
| return `CASE WHEN COUNT(DISTINCT ${value}) > COUNT(*) * ${maxDistinctRatio} | ||
| THEN NULL ELSE ( | ||
| SELECT '[' + STRING_AGG(CONCAT('{"value":"', REPLACE(CAST(v AS nvarchar(max)), '"', '\\"'), '","count":', CAST(n AS nvarchar(20)), '}'), ',') + ']' |
| output, | ||
| expression: definition.expression({ | ||
| table, | ||
| column: field ? sqlIdentifier(field.name) : undefined, |
| FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE k | ||
| WHERE k.TABLE_CATALOG = ${db} | ||
| ORDER BY k.TABLE_NAME, k.ORDINAL_POSITION |
| models: tables.map(({ table_name }) => { | ||
| const fields = columnRows | ||
| .filter((column) => column.table_name === table_name) | ||
| .map((column) => ({ name: column.name, type: column.type, notNull: !bool(column.nullable) })); |
|
Addressed the open Copilot findings on the SQL Server data source (head 35394dc):
Tests added under |
…error handling Signed-off-by: DoubleCore <doublecore@users.noreply.github.com>
|
修复已推送
|
a070589 to
1b3279f
Compare
|
本轮修复已推送(commit 解冲突 — 与 2 条未解决 review:
验证:sqlserver 相关测试( |
4055610 to
70d2b17
Compare
|
本轮续修已推送原 PR head
未执行真实 SQL Server live 端到端测试,以上均为离线 mock 验证;fork PR 的 GitHub Actions 仍需维护者触发/批准。 |
|
目前主分支已经支持了 SQL Server。此pr不考虑合入。 不过不用担心,这个 pr 会正常评分。 |


Summary
Add a read-only Microsoft SQL Server remote data source to AVA (issue #1011). Users can now connect to a SQL Server, discover its schema, run read-only T-SQL queries, and get per-column profiles, through both the SDK and the CLI.
What's included
tedious(default) — production TDS driver, opened withApplicationIntent=ReadOnly, loaded via a runtimerequireso the module has no hard dependency ontedious.mock— in-memory connector servingINFORMATION_SCHEMAcatalog views and a small read-only T-SQL subset (SELECT / TOP / WHERE / GROUP BY / HAVING / ORDER BY / aggregates). No server or network required (demos, CI, docs).INFORMATION_SCHEMA.TABLES/.COLUMNS/.KEY_COLUMN_USAGE, mapping primary keys ontoSchema.primaryKey.SELECT TOP (N)(T-SQL has noLIMIT) withmaxRows(200) /maxResultBytes(1 MiB); idempotentdispose()thatclose()s the connection.--enginehelp,createDatasetengine selection, and the sessionprotocolzod schema (plus instanceName/port mutual-exclusion validation).__tests__/remote/sqlserver.test.ts, 27 cases) covering schema discovery, queries, error handling, result caps, read-only validation, and dispose — all on the mock adapter.data/sources.mdx+engines/remote.mdx, and a module README, with two natural-language analysis examples over seeded sales data.Notes
tediouspath is structurally typed and runtime-required; users installtediousfor real connections.tsc --noEmitpasses; the only remaining diagnostic is a pre-existing one insrc/duckdb/loaders/index.tspresent on the base branch.vitestnew tests pass (27/27); existing (pre-existing) failures infeishu/cli-session(home-dir credential tests) and a flaky worker crash are unrelated and reproduced on the base commit.Closes #1011