Skip to content

Add MSSQL engine for parse and analyze via teesql - #4571

Merged
kyleconroy merged 2 commits into
mainfrom
claude/mssql-teesql-support-fwilp9
Aug 19, 2026
Merged

Add MSSQL engine for parse and analyze via teesql#4571
kyleconroy merged 2 commits into
mainfrom
claude/mssql-teesql-support-fwilp9

Conversation

@kyleconroy

Copy link
Copy Markdown
Collaborator

Adds a new mssql engine backed by github.com/sqlc-dev/teesql, a T-SQL parser producing a SqlScriptDOM-compatible AST, and wires it into sqlc parse and sqlc analyze.

What's included

internal/engine/mssql

  • parse.go — parses T-SQL via teesql and computes statement spans with a scanner aware of T-SQL string/[bracket] quoting and --//* */ comments, plus a UTF-16→byte offset map (teesql mirrors ScriptDom's UTF-16 offsets).
  • convert.go — converts teesql's AST to sqlc's internal AST:
    • SELECT with joins, CTEs, GROUP BY/HAVING, ORDER BY, TOP, OFFSET … FETCH, DISTINCT, and UNION/EXCEPT/INTERSECT
    • INSERT/UPDATE/DELETE, with OUTPUT clauses mapped to returning lists (INSERTED/DELETED qualifiers stripped so columns resolve against the target table)
    • @name parameters become numbered parameters, with repeated uses of a name sharing a number
    • CASE/IIF/COALESCE/NULLIF, CAST/CONVERT and their TRY_ variants, LIKE/IN/BETWEEN/EXISTS, window functions
    • CREATE/ALTER/DROP TABLE with T-SQL nullability rules: columns are nullable by default; NOT NULL, IDENTITY, and column- or table-level PRIMARY KEY force not-null
    • The dbo schema maps to the catalog's default namespace, so dbo.table and table resolve identically
  • dialect/ — analysis-core seed: 34 SQL Server types with aliases, comparison/arithmetic/cast rules, and function signatures (count, count_big, sum/avg/min/max overloads, date/time functions, newid, len, string functions)
  • reserved.go — the T-SQL reserved keyword list

Wiring

  • EngineMSSQL config constant; the engine always analyzes through the core (like ClickHouse and GoogleSQL, it has no legacy path)
  • sqlc parse --dialect mssql and sqlc analyze --dialect mssql (alias sqlserver); docs updated

Tests

  • End-to-end cases under parse_basic/mssql, analyze_basic/mssql, and analyze_params/mssql with committed goldens

Notes

  • Known shared limitations of the core analyzer (not MSSQL-specific): parameters inside IN (subquery) and in OFFSET/FETCH clauses are not reported.
  • Upstream quirk found while testing: teesql rejects stats as a CTE name (lexed as a keyword) — worth a follow-up fix in the teesql repo.

Full test suite (go test --tags=examples ./...) passes against live PostgreSQL and MySQL.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FrnQ4EoZ3WCWWrSsm8bhCP


Generated by Claude Code

claude added 2 commits August 18, 2026 22:03
Add a new mssql engine backed by github.com/sqlc-dev/teesql, a T-SQL
parser producing a SqlScriptDOM-compatible AST. The engine converts
teesql's AST into sqlc's internal AST and analyzes queries through the
analysis core, seeded with SQL Server's type system.

- internal/engine/mssql: parser, AST converter, reserved keywords and
  dialect seed (types, functions, operator rules)
- Wire the engine into the compiler's core-analysis path and the parse
  and analyze commands as the mssql (alias sqlserver) dialect
- Named @parameters share a number across repeated uses; OUTPUT clauses
  map to returning lists with INSERTED/DELETED qualifiers stripped; the
  dbo schema maps to the catalog's default namespace
- End-to-end coverage under parse_basic, analyze_basic and
  analyze_params

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FrnQ4EoZ3WCWWrSsm8bhCP
Address review findings on the initial engine:

- DELETE dropped its FROM clause, so the T-SQL join form
  (DELETE b FROM books b JOIN ...) failed to resolve. UPDATE and DELETE
  now resolve an alias target against the FROM clause: the matching
  relation becomes the statement's target, and the ON conditions of any
  inner join dissolved by pulling it out move to the WHERE clause.
  Relations under outer joins are left alone.
- AST Location fields carried teesql's UTF-16 code-unit offsets while
  StmtLocation/StmtLen are byte offsets; the converter now maps
  locations through the same byte-offset table as statement spans.
- Drop the unreachable "within group" reserved-keyword case: keywords
  are checked one identifier token at a time.
- Cover INSERT ... OUTPUT and the UPDATE/DELETE alias forms end to end
  under analyze_dml/mssql.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FrnQ4EoZ3WCWWrSsm8bhCP
@kyleconroy
kyleconroy merged commit 0d8f090 into main Aug 19, 2026
13 checks passed
@kyleconroy
kyleconroy deleted the claude/mssql-teesql-support-fwilp9 branch August 19, 2026 04:50
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.

2 participants