Skip to content

[codex] Add MSSQL RQBv2 support#5886

Draft
quesurifn wants to merge 9 commits into
drizzle-team:betafrom
quesurifn:mssql-rqbv2
Draft

[codex] Add MSSQL RQBv2 support#5886
quesurifn wants to merge 9 commits into
drizzle-team:betafrom
quesurifn:mssql-rqbv2

Conversation

@quesurifn

@quesurifn quesurifn commented Jun 12, 2026

Copy link
Copy Markdown

What changed

Adds Relational Queries v2 support for the MSSQL dialect so db.query.* works with defineRelations, matching the RQBv2 surface already available in pg/mysql/sqlite/singlestore.

Key pieces:

  • Adds a V2 MSSQL relational query builder while keeping the existing V1 _query path intact.
  • Maps RQBv2 lateral relation queries to SQL Server OUTER APPLY plus FOR JSON PATH/JSON_QUERY.
  • Preserves nested JSON shape with JSON_QUERY, returns empty many-relations as [], and parses top-level FOR JSON chunks through the shared RQBv2 row mapper.
  • Threads V2 relation generics through MSSQL database/session/transaction and node-mssql driver entry points.
  • Adds deterministic fallback ordering for offset without orderBy: PK columns first, then all exposed columns for views/no-PK sources, and 1 only when no columns exist.
  • Adds MSSQL db.$count, raw db.execute(), withReplicas, and full query-result caching support including drizzle({ cache }), $withCache(), cache-aware prepared query execution, and mutation invalidation metadata.
  • Adds SQL Server indexed-view DDL support for schema-bound views with clustered/nonclustered indexes and drizzle-kit pull round-trip coverage.
  • Adds MSSQL native column builders for uniqueidentifier, xml, money, smallmoney, rowversion, geography, and geometry.
  • Extends MSSQL index DSL/kit metadata with per-column .asc() / .desc(), INCLUDE, and WITH (FILLFACTOR = ..., ONLINE = ...) SQL emission.
  • Adds drizzle-kit MSSQL snapshot v3 migration for index metadata, pull/codegen support for descending keys, included columns, and persisted fill factor.
  • Implements the existing typed MSSQL FOR XML and FOR BROWSE select modes in the dialect.

Root cause

MSSQL still only exposed the legacy _relations.ts/RQBv1 path, so libraries that require RQBv2, including @pothos/plugin-drizzle, could not use SQL Server. The dialect also needed SQL Server-specific JSON aggregation and lateral-query equivalents instead of the pg/mysql primitives used by other RQBv2 dialects.

One live SQL Server issue found during validation: SQL Server rejects ORDER BY inside derived tables unless paired with TOP, OFFSET, or XML/JSON context. Nested ordered relation subqueries without a limit now emit OFFSET 0 ROWS to preserve order legally.

Validation

Passed during the RQBv2/cache/indexed-view work:

  • pnpm --filter drizzle-orm build
  • pnpm --filter drizzle-orm test:types
  • pnpm exec vitest run tests/mssql-rqbv2.test.ts
  • pnpm --filter integration-tests test:types
  • Live SQL Server RQBv2 integration: MSSQL_CONNECTION_STRING=... pnpm --filter integration-tests exec vitest run tests/mssql/mssql-rqbv2.test.ts --reporter=verbose --silent=false (9 tests)
  • pnpm --filter drizzle-kit test:types
  • MSSQL_CONNECTION_STRING=... pnpm --filter drizzle-kit exec vitest run tests/mssql/views.test.ts --reporter=verbose (36 tests)
  • Pothos plugin smoke with MSSQL RQBv2 relation resolution and $count
  • git diff --check
  • Commit hook: pnpm format:check --allow-no-files and pnpm lint:check

Passed after the latest MSSQL native-type/index/FOR-mode follow-up:

  • pnpm --filter drizzle-orm test:types
  • git diff --check
  • Targeted pnpm oxlint --max-warnings=0 ... over touched ORM/kit files
  • Commit hook: pnpm format:check --allow-no-files and pnpm lint:check

Current local verification blockers after the latest follow-up:

  • pnpm --filter drizzle-orm build hangs locally in bun --bun run scripts/build.ts, so drizzle-orm/dist could not be refreshed in this checkout.
  • Because kit type tests resolve drizzle-orm through drizzle-orm/dist, pnpm --filter drizzle-kit test:types currently reports stale-package missing exports/methods from before the latest follow-up.
  • Focused drizzle-kit MSSQL tests for the new native type/index snapshots collect, but fail during setup before assertions because the local SQL Server config uses 127.0.0.1 with TLS SNI and tedious rejects IP-address servername.

Notes

Minimum target remains SQL Server 2016+ / Azure SQL because this relies on FOR JSON, JSON_QUERY, and OFFSET/FETCH.

When a query uses offset without an explicit orderBy, MSSQL injects a fallback ORDER BY because SQL Server requires it. PK-backed tables use aliased primary-key columns for deterministic pagination. Views and no-PK sources fall back to all exposed columns only as a best-effort SQL Server compatibility path; production pagination should still pass an explicit orderBy with the desired business ordering.

ONLINE = ON is supported for SQL emission as an index create/rebuild execution option. SQL Server does not expose it as durable index metadata, so pull round trips can preserve fill_factor but cannot prove a historical ONLINE choice.

Fulltext and columnstore indexes are not modeled by the normal MSSQL b-tree index builder in this PR. They are separate SQL Server index families with different required clauses and should get dedicated APIs if maintainers want them.

I did not add a refresh-materialized-view builder for MSSQL. SQL Server does not have PostgreSQL/Cockroach-style materialized views or a REFRESH MATERIALIZED VIEW statement. This PR adds SQL Server indexed-view support instead, which is the closest SQL Server-specific analogue.

The committed Pothos smoke uses t.relatedField with an explicit list type because the integration test environment can load mixed ESM/CJS Drizzle module identities, while the plugin's default t.relation list inference uses instanceof Many. The test still exercises Pothos' Drizzle selection hook resolving an MSSQL RQBv2 relation through db.query, and also asserts a postsCount field backed by the real MSSQL db.$count.

The 1.0.0 beta/RC type surface is moving quickly. This should land upstream rather than being carried as a patched node_modules fork.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant