T-SQL (SQL Server)

How 3XCode detects, plans, and converts Transact-SQL (stored procedures, functions, views, and triggers) from SQL Server and Azure SQL into production PySpark.

Overview

T-SQL (Transact-SQL) is Microsoft's procedural extension to SQL, used by SQL Server, Azure SQL Database, and Azure Synapse Analytics. It is one of the source dialects 3XCode's conversion pipeline recognizes natively, represented internally as the tsql value of the pipeline's SQLDialect enum, alongside plsql (Oracle), plpgsql (PostgreSQL), mysql, ansi (generic ANSI SQL), and spark_sql.

When you run 3xcode pyspark convert against a .sql file written in T-SQL, the Discovery phase classifies it as tsql, inventories every stored procedure, function, view, and trigger it contains, and hands that inventory to Planning, which decides conversion order and pulls in only the T-SQL-relevant knowledge (date functions, cursor patterns, dynamic SQL handling, and so on) needed to convert it correctly.

How T-SQL Is Detected

Detection happens in two separate layers during the Discovery phase, and neither one requires you to tell 3XCode what dialect a file is in.

Dialect Classification (LLM)

Claude reads the file during Discovery and classifies it into the SQLDialect enum. A field validator normalizes dozens of possible spellings ('Transact-SQL', 'Azure SQL', and 'Synapse' all normalize to tsql), so variation in how the source labels itself doesn't affect classification.

Platform Fingerprinting (deterministic)

A separate, regex-only pass scores the file against syntax markers for 10 vendor platforms (including SQL Server) with zero LLM cost. It returns the winning platform, a confidence label, and the exact markers that fired, so platform detection is fully explainable rather than a black box.

Every generated PySpark file gets a one-line header comment naming the detected source platform, confidence level, and matched markers, so you can always see how a given .py output was classified. Discovery also builds a full object inventory for the file: name, type, exact line range, parameters, cross-object references, and flags for cursors, dynamic SQL, and transactions, which downstream phases use to plan and convert.

What Gets Converted

The Planning phase topologically sorts discovered objects and converts them in dependency order (views and standalone functions first, then procedures, then triggers), so a procedure that references a view always sees that view's converted signature rather than a guess.

Stored Procedures

Converted into PySpark modules with private step/helper functions and a run_pipeline(spark, params) orchestrator, preserving the procedure's logical flow.

Views & Scalar/Table Functions

Converted first in the dependency order, since procedures and triggers that reference them need real, converted signatures, not placeholders, to convert correctly.

Triggers

Inventoried and converted with their referenced tables and cross-object dependencies resolved, following the same Views → Functions → Procedures → Triggers precedence.

Cursors

Detected via a has_cursor flag during Discovery and flagged for the conversion agent to rewrite as native PySpark window functions rather than row-by-row Python loops, since Python UDF loops are dramatically slower than native F.xxx operations at scale.

Known Behavioral Differences

3XCode's validation and auto-fix phases check generated PySpark against a knowledge base of known T-SQL-to-Spark behavioral gaps. The most relevant ones for T-SQL sources:

T-SQL → PySpark gotchas the pipeline checks for

ConstructGotchaHandling
DATEDIFFArgument order is reversed between T-SQL and Spark SQL.Flagged during Validation; targeted by Auto-Fix when detected.
CursorsT-SQL cursors have no direct PySpark equivalent. Row-by-row Python loops are 50–100x slower than native operations.Discovery sets has_cursor; conversion is instructed to rewrite as window functions where possible, otherwise flagged for manual review.
Dynamic SQL / sp_executesqlNo safe automatic transform exists for dynamically constructed SQL text.Classified as a manual-review item, never auto-fixed.
OPENROWSETExternal/ad-hoc data access construct with no PySpark equivalent.Classified as a manual-review item, never auto-fixed.
Transactions (BEGIN TRAN / COMMIT / ROLLBACK)T-SQL transaction control has no direct PySpark equivalent.Discovery sets has_transaction; classified as a manual-review item.
BIT columnsNULL handling on BIT columns differs from PySpark's boolean/nullable semantics.Checked during Validation's NULL-semantics review.
String comparisonsSpark is case-sensitive by default, which can differ from the source collation's comparison behavior.Checked during Validation.
Decimal arithmeticPrecision can be lost across certain arithmetic operations when types are mapped.Checked during Validation; flagged as a TODO if unresolved.

Issues the pipeline can't safely auto-fix (cursors requiring a rewrite, dynamic SQL, and transaction logic) are surfaced as prioritized, developer-facing action items after conversion, each with prescriptive guidance on how to resolve it by hand.

Converting a T-SQL File

No flag is needed to tell 3XCode a file is T-SQL. Dialect and platform are detected automatically during Discovery. Just point the pyspark agent at your file or directory:

Terminal
# Convert a single T-SQL / SQL Server script
3xcode pyspark convert stored_procs.sql

# Dry-run: discovery + planning only, no conversion
3xcode pyspark analyze stored_procs.sql

# Convert every .sql file in a directory (bulk mode)
3xcode pyspark convert --dir ./sql/ --session "sqlserver-migration" -w 4

# Find the real session ID for an interrupted bulk session, then resume it
3xcode session list
3xcode pyspark convert --resume <session-id-from-list>

After conversion, check <stem>_audit.md in your output directory for the per-file confidence/completion grade and the list of items that need manual review: cursors, dynamic SQL, and transaction blocks in particular are common T-SQL constructs that land there rather than being silently auto-converted.

FAQ

Do I need to specify that my file is T-SQL?

No. Dialect classification and platform fingerprinting both run automatically during the Discovery phase. There is no --dialect flag to set.

Does 3XCode support Azure SQL and Azure Synapse too?

Yes, the dialect classifier normalizes labels like "Azure SQL" and "Synapse" to the same tsql dialect as SQL Server, since they share T-SQL syntax.

What happens to cursors and dynamic SQL that can't be auto-converted?

They're never silently dropped or guessed at. Discovery flags them and they're classified as manual-review items (excluded from the Auto-Fix pass entirely rather than attempted and reverted), and they appear in the audit report's developer action items with specific guidance on how to rewrite them by hand.

Is my T-SQL source code sent to the 3XDE backend?

No. Source SQL is never sent to the 3XDE backend. The CLI talks to your configured LLM provider directly for conversion. The backend only handles auth, licensing, and provider-key metadata.