Skip to content

OZTPR/T-Lift

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

T-Lift

T-Lift is a T-SQL precompiler that lets developers use directive-based meta-code within stored procedures to generate controlled, dynamic T-SQL. It is designed for teams that understand when and why dynamic SQL helps SQL Server build more predictable execution plans, but want a cleaner, safer, and more comfortable way to apply it without hand-crafting dynamic SQL everywhere.

Written entirely in T-SQL. Ships as a single stored procedure (sp_tlift).


Table of Contents


The Idea in a Nutshell aka 'Hello World!'

Consider to get an idea how T-Lift works this common pattern in SQL Server stored procedures:

CREATE OR ALTER PROCEDURE dbo.SearchOrders
    @CustomerID INT = NULL,
    @Status NVARCHAR(20) = NULL
AS
SELECT o.OrderID, o.CustomerID, o.OrderDate, o.Status, o.TotalAmount
FROM dbo.Orders o
WHERE (@CustomerID IS NULL OR o.CustomerID = @CustomerID)
  AND (@Status IS NULL OR o.Status = @Status)

This is a classic "catch-all" or "one-size-fits-all" query. It works correctly, but the SQL Server query optimizer cannot produce an optimal plan for it. The optimizer must account for every possible NULL/non-NULL combination at once, which typically means a full scan regardless of which parameters you actually supply.

Worse, the execution plan that gets cached depends on whichever parameter values happened to come in first. Call it with @CustomerID = 42 and SQL Server might cache a plan with an index seek. Call it next with no parameters — and that seek-based plan is reused for a full table scan scenario. The logical reads can differ by orders of magnitude for the same result set, depending purely on compilation order.

This is parameter sniffing at work. It is not a bug — it is how SQL Server caching works. But it means that this common coding pattern quietly produces unpredictable performance in production.

There is no index that fixes this structurally. The issue is in how the query is written.

The Known Solution: Dynamic SQL

The SQL Server community has long recommended dynamic SQL via sp_executesql for this kind of scenario. By building only the predicates that actually apply at runtime, you let the optimizer see a simpler, more specific query — and it produces a better plan.

But writing dynamic SQL by hand is tedious. You lose IntelliSense, syntax highlighting, and the ability to just highlight and execute a query in SSMS. The code is harder to read, harder to maintain, and harder to debug.

That is the trade-off T-Lift tries to eliminate.


What T-Lift Does

T-Lift reads your existing stored procedure, looks for directives you place inside T-SQL comments, and generates a new version of that procedure using dynamic SQL and sp_executesql.

Because the directives are just comments, your original procedure remains fully valid and executable. You can develop, test, and debug as usual in SSMS or any other editor. When you are ready, you run T-Lift to produce the optimized version.

The basic idea: you annotate your procedure, T-Lift renders it.


Installation

  1. Grab sp_tlift.sql from this repository.
  2. Execute it in a separate user database (not the database where your target procedures live).

T-Lift reads metadata from other databases via sys.sql_modules and sys.parameters, so the executing user needs appropriate read permissions on the target database.

-- Example: install into a dedicated database
USE [TLift_Engine];
GO

-- Execute the sp_tlift.sql script
-- (via SSMS "Open File" or sqlcmd -i sp_tlift.sql)

You can also ask T-Lift to explain itself:

EXEC dbo.sp_tlift @help = 1;

Testing

The repository includes a small SQL Server regression harness under intern_stuff/.

  1. Run intern_stuff/test_setup.sql to create TLift_Engine, TLift_TestDB, and the sample data set.
  2. Execute sp_tlift.sql in TLift_Engine.
  3. Run intern_stuff/test_procedures.sql to create the annotated source procedures.
  4. Run intern_stuff/run_tests.sql to render, deploy, and execute the full suite.
  5. Inspect TLift_TestDB.dbo.TestResults for persisted pass/fail results.

The demo script in demos/ assumes the same split: TLift_Engine hosts sp_tlift, and TLift_TestDB hosts the procedures being rendered.


Basic Usage

DECLARE @dynsql NVARCHAR(MAX);

EXEC dbo.sp_tlift
    @DatabaseName   = 'YourDatabase',
    @ProcedureName  = 'YourProcedure',
    @Result         = @dynsql OUTPUT;

PRINT @dynsql;

T-Lift reads the source procedure, processes directives, and returns the rendered dynamic SQL procedure as a string in @Result. From there you can review it, adjust it, and deploy it.


Quick Start

Here is a complete end-to-end walkthrough. We start with a catch-all query, annotate it with T-Lift directives, and render it.

1. Create the source procedure

This is a standard catch-all query — it works correctly but suffers from parameter sniffing:

CREATE OR ALTER PROCEDURE dbo.SearchOrders
    @CustomerID INT = NULL,
    @Status NVARCHAR(20) = NULL
AS
                                        --#[
SELECT o.OrderID, o.CustomerID, o.OrderDate, o.Status, o.TotalAmount
FROM dbo.Orders o
WHERE                                   --#if @CustomerID IS NOT NULL OR @Status IS NOT NULL
(                                       --#-
@CustomerID IS NULL OR                  --#-
o.CustomerID = @CustomerID              --#if @CustomerID IS NOT NULL
)                                       --#-
AND                                     --#if @CustomerID IS NOT NULL AND @Status IS NOT NULL
(                                       --#-
@Status IS NULL OR                      --#-
o.Status = @Status                      --#if @Status IS NOT NULL
)                                       --#-
                                        --#]

Note: The procedure is still fully valid T-SQL. The --# directives are just comments — you can execute this procedure as-is in SSMS.

2. Render it with T-Lift

DECLARE @dynsql NVARCHAR(MAX);

EXEC dbo.sp_tlift
    @DatabaseName   = 'YourDatabase',
    @ProcedureName  = 'SearchOrders',
    @Result         = @dynsql OUTPUT;

PRINT @dynsql;

3. Review the output

T-Lift produces a new procedure that builds only the applicable predicates at runtime:

CREATE PROCEDURE dbo.tlift_version_of_your_sproc
    @CustomerID INT = NULL,
    @Status NVARCHAR(20) = NULL
AS
DECLARE @sql NVARCHAR(MAX) = N''
SET @sql = @sql + 'SELECT o.OrderID, o.CustomerID, o.OrderDate, o.Status, o.TotalAmount' + CHAR(13)+CHAR(10)
SET @sql = @sql + 'FROM dbo.Orders o' + CHAR(13)+CHAR(10)
IF @CustomerID IS NOT NULL OR @Status IS NOT NULL
    SET @sql = @sql + 'WHERE' + CHAR(13)+CHAR(10)
IF @CustomerID IS NOT NULL
    SET @sql = @sql + 'o.CustomerID = @CustomerID' + CHAR(13)+CHAR(10)
IF @CustomerID IS NOT NULL AND @Status IS NOT NULL
    SET @sql = @sql + 'AND' + CHAR(13)+CHAR(10)
IF @Status IS NOT NULL
    SET @sql = @sql + 'o.Status = @Status' + CHAR(13)+CHAR(10)
EXEC sp_executesql @sql, N'@CustomerID int, @Status nvarchar(20)', @CustomerID, @Status

Now each combination of parameters gets its own optimized plan. Call it with @CustomerID = 42 — only the CustomerID predicate is included. Call it with no parameters — no WHERE clause at all.

4. Deploy

Review the rendered output, then execute it in your target database to create the optimized procedure. You can customize the output procedure name with the @ProcedureNameNew parameter.


Directive Reference

All directives live inside T-SQL line comments (--#...), so they do not affect the original procedure in any way.

Dynamic SQL Sections

Mark which parts of your procedure should become dynamic SQL.

--#[              Open a dynamic SQL section
--#]              Close a dynamic SQL section

Only code between --#[ and --#] is rendered as dynamic SQL. Everything outside these brackets passes through unchanged. A single procedure can have multiple sections.

CREATE OR ALTER PROCEDURE dbo.SearchCustomers
    @City NVARCHAR(50) = NULL
AS
                                    --#[
SELECT c.CustomerID, c.FirstName, c.LastName, c.City
FROM dbo.Customers c
WHERE                               --#if @City IS NOT NULL
(                                   --#-
@City IS NULL OR                    --#-
c.City = @City                      --#if @City IS NOT NULL
)                                   --#-
                                    --#]

Single-Line Conditionals

--#if <condition>

Controls whether the line it is placed on is included in the rendered dynamic SQL. The condition is evaluated at runtime in the generated procedure.

SELECT c.CustomerID, c.FirstName, c.LastName
FROM dbo.Customers c
WHERE                               --#if @CustomerID IS NOT NULL
c.CustomerID = @CustomerID          --#if @CustomerID IS NOT NULL

When @CustomerID IS NULL, the rendered SQL simply becomes:

SELECT c.CustomerID, c.FirstName, c.LastName
FROM dbo.Customers c

No WHERE clause at all — and the optimizer knows it.

Remove Lines

--#-

Marks a line to be removed entirely in the dynamic version. Use this for the static fallback logic (@param IS NULL OR ...) that you need in the original procedure but not in the dynamic one.

WHERE                               --#if @City IS NOT NULL
(                                   --#-
@City IS NULL OR                    --#-
c.City = @City                      --#if @City IS NOT NULL
)                                   --#-

The lines marked --#- are the "glue" that makes the original procedure work without dynamic SQL. T-Lift strips them out because the --#if conditions already handle the logic.

Block Conditionals

For multi-line blocks that should all be governed by one condition:

--#{if <condition>      Open a conditional block
--#}                    Close it
CREATE OR ALTER PROCEDURE dbo.OrderReport
    @CustomerID INT = NULL,
    @IncludeDetails BIT = 0
AS
                                    --#[ OrderSummary
SELECT o.OrderID, o.CustomerID, o.OrderDate, o.TotalAmount
FROM dbo.Orders o
WHERE                               --#if @CustomerID IS NOT NULL
o.CustomerID = @CustomerID          --#if @CustomerID IS NOT NULL
                                    --#]

                                    --#{if @IncludeDetails = 1
                                    --#[ OrderDetails
SELECT oi.OrderItemID, oi.OrderID, oi.ProductID, oi.Quantity, oi.LineTotal
FROM dbo.OrderItems oi
INNER JOIN dbo.Orders o ON oi.OrderID = o.OrderID
WHERE                               --#if @CustomerID IS NOT NULL
o.CustomerID = @CustomerID          --#if @CustomerID IS NOT NULL
                                    --#]
                                    --#}

When @IncludeDetails = 0, the entire detail query — including its dynamic SQL section — is skipped.

Block Conditionals Inside Dynamic SQL Sections

--#{if blocks can also be used inside a --#[ section to conditionally include groups of lines — such as an optional WHERE clause — with the condition stated only once. This is the cleanest way to handle a single optional filter:

CREATE OR ALTER PROCEDURE dbo.SearchByCustomer
    @CustomerID INT = NULL
AS
                                    --#[ Search
SELECT c.CustomerID, c.FirstName, c.LastName, c.City
FROM dbo.Customers c
                                    --#{if @CustomerID IS NOT NULL
WHERE
c.CustomerID = @CustomerID
                                    --#}
                                    --#]

When @CustomerID is NULL, the rendered SQL has no WHERE clause at all. When non-NULL, it includes WHERE c.CustomerID = @CustomerID. The condition appears once on the --#{if line instead of being repeated on every line.

You can still combine --#{if with --#- for catch-all static SQL patterns:

                                    --#{if @CustomerID IS NOT NULL
WHERE
(                                   --#-
@CustomerID IS NULL OR              --#-
c.CustomerID = @CustomerID
)                                   --#-
                                    --#}

Else and Else-If

Inside a block conditional, you can add alternative branches:

--#else                  Else branch
--#{elseif <condition>   Else-if branch with a new condition
CREATE OR ALTER PROCEDURE dbo.CustomerList
    @SortMode INT = 0
AS
                                    --#[ CustList
SELECT c.CustomerID, c.FirstName, c.LastName, c.City
FROM dbo.Customers c
                                    --#]

                                    --#{if @SortMode = 1
PRINT 'Sorting by name'
                                    --#{elseif @SortMode = 2
PRINT 'Sorting by city'
                                    --#else
PRINT 'Default sort order'
                                    --#}

This renders as a standard IF / ELSE IF / ELSE chain in the output.

Comment-Out Lines

--#c

Keeps the line in the rendered output, but comments it out (prefixed with --). Useful for keeping reference information visible without executing it.

ORDER BY o.OrderDate DESC           --#c

In the rendered output, this becomes:

--ORDER BY o.OrderDate DESC

Named Sections

You can give a dynamic SQL section a label by placing text after --#[. The label is embedded as a SQL comment (/*label*/) in the rendered sp_executesql call, making it easy to find specific queries in the plan cache.

                                    --#[ CustomerSearch
SELECT c.CustomerID, c.FirstName, c.LastName
FROM dbo.Customers c
WHERE                               --#if @City IS NOT NULL
c.City = @City                      --#if @City IS NOT NULL
                                    --#]

You can then find cached plans for this section:

SELECT cplan.usecounts, qtext.text, qplan.query_plan
FROM sys.dm_exec_cached_plans AS cplan
CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS qtext
CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qplan
WHERE qtext.text LIKE '%/*CustomerSearch*/%'
  AND qtext.text NOT LIKE '%dm_exec_cached_plans%'
ORDER BY cplan.usecounts DESC;

Named Conditions

--#define <name> = <condition>

Defines a reusable condition that can be referenced by name in --#if, --#{if, and --#{elseif directives. This eliminates repetition when the same condition appears in multiple places.

The --#define directive emits no output — it is metadata only. Place it before any --#[ section that uses it.

CREATE OR ALTER PROCEDURE dbo.OrderReport
    @CustomerID INT = NULL,
    @IncludeDetails BIT = 0
AS
                                    --#define custFilter = @CustomerID IS NOT NULL

                                    --#[ OrderSummary
SELECT o.OrderID, o.CustomerID, o.OrderDate, o.TotalAmount
FROM dbo.Orders o
                                    --#{if custFilter
WHERE
o.CustomerID = @CustomerID
                                    --#}
                                    --#]

                                    --#{if @IncludeDetails = 1
                                    --#[ OrderDetails
SELECT oi.OrderItemID, oi.OrderID, oi.ProductID, oi.Quantity, oi.LineTotal
FROM dbo.OrderItems oi
INNER JOIN dbo.Orders o ON oi.OrderID = o.OrderID
                                    --#{if custFilter
WHERE
o.CustomerID = @CustomerID
                                    --#}
                                    --#]
                                    --#}

Without --#define, the condition @CustomerID IS NOT NULL would appear on every --#if / --#{if line — in this example, that is 4 repetitions. With a named condition, it is defined once and referenced by name.

Rules:

  • Names must not start with @ (to avoid confusion with parameters).
  • Names are case-insensitive.
  • A --#define must appear before any directive that references it (top-to-bottom processing).
  • T-Lift warns if a defined condition is never used.

Block Removal

--#{-             Open a removal block
--#-}             Close a removal block

All lines between --#{- and --#-} are treated as removed (like --#-), without needing per-line annotations. This reduces noise when you have several consecutive scaffolding lines.

                                    --#{if @CustomerID IS NOT NULL
WHERE
                                    --#{-
(
@CustomerID IS NULL OR
                                    --#-}
c.CustomerID = @CustomerID
                                    --#{-
)
                                    --#-}
                                    --#}

Block removal is most useful when you have 4+ consecutive lines that all need --#-. For fewer lines, individual --#- annotations may be simpler.

Recompile Hint

--#recompile

Place this directive anywhere inside a dynamic SQL section. T-Lift will append OPTION(RECOMPILE) to the sp_executesql call for that section. Use this when you want fresh plans on every execution — for example, when parameter distributions are highly skewed and even the dynamic SQL approach benefits from recompilation.

                                    --#[ HeavyReport
                                    --#recompile
SELECT ...
FROM ...
WHERE ...                           --#if @DateFrom IS NOT NULL
                                    --#]

Buckets (Plan Cache Segmentation)

--#buckets @param: value1, value2, value3

Place this directive on its own line inside a --#[ / --#] section. T-Lift generates CASE-based bucket variables that segment the plan cache based on parameter value ranges. Each range gets its own cached plan, which is useful when the optimal plan shape varies significantly depending on the parameter's magnitude.

The values define the boundaries between buckets. For example, --#buckets @Amount: 50, 100, 200 creates four buckets:

Bucket Condition
00 @Amount < 50
01 @Amount >= 50 AND @Amount < 100
02 @Amount >= 100 AND @Amount < 200
03 @Amount >= 200

The bucket value is prepended as a SQL comment (/*01*/) to the dynamic SQL, so sp_executesql caches a separate plan for each bucket.

CREATE OR ALTER PROCEDURE dbo.OrdersByAmount
    @MinAmount DECIMAL(10,2) = NULL
AS
                                                --#[ OrdersByAmount
                                                --#buckets @MinAmount: 50, 100, 200
SELECT o.OrderID, o.CustomerID, o.TotalAmount
FROM dbo.Orders o
WHERE                                           --#if @MinAmount IS NOT NULL
o.TotalAmount >= @MinAmount                     --#if @MinAmount IS NOT NULL
                                                --#]

You can use multiple --#buckets directives in the same section for multi-dimensional segmentation.


Variables vs. Parameters

T-Lift automatically picks up procedure parameters from sys.parameters — no extra work needed. But T-SQL variables declared inside the procedure body are a different story: the optimizer cannot see their values, and T-Lift cannot read them from metadata.

If you use local variables inside a dynamic SQL section, you need to tell T-Lift about them with two directives.

Step 1: Mark the Declaration

--#var

Place this on the DECLARE line of any variable you want to pass into dynamic SQL.

DECLARE @ActiveOnly BIT = 1;               --#var
DECLARE @MinPrice DECIMAL(10,2) = 9.99;    --#var

One variable per line. Multi-variable declarations on a single line are not supported:

-- Not supported:
DECLARE @v1 INT = 1, @v2 INT = 2   --#var

-- Supported:
DECLARE @v1 INT = 1                 --#var
DECLARE @v2 INT = 2                 --#var

T-Lift supports a wide range of data types — INT, VARCHAR, DECIMAL, DATETIME2, UNIQUEIDENTIFIER, NVARCHAR(MAX), and many more.

Step 2: Register in the Dynamic Section

--#usevar @var1, @var2

Inside a --#[ / --#] section, this tells T-Lift to include these variables in the sp_executesql parameter list. The directive can go on any line within the section.

CREATE OR ALTER PROCEDURE dbo.ActiveProducts
    @Category NVARCHAR(50) = NULL
AS
DECLARE @ActiveOnly BIT = 1;               --#var

                                            --#[ ActiveProds
SELECT p.ProductID, p.ProductName,          --#usevar @ActiveOnly
       p.Category, p.UnitPrice
FROM dbo.Products p
WHERE                                       --#if @Category IS NOT NULL OR @ActiveOnly = 1
p.Category = @Category                      --#if @Category IS NOT NULL
AND                                         --#if @Category IS NOT NULL AND @ActiveOnly = 1
p.IsActive = @ActiveOnly                    --#if @ActiveOnly = 1
                                            --#]

Now both the parameter @Category and the variable @ActiveOnly are passed to sp_executesql, and the optimizer can see both values at compile time.


Wrapper Procedures

For scenarios where you want separate plan cache entries per usage pattern — not just per query shape within dynamic SQL — T-Lift can generate wrapper procedures. A wrapper is a dispatcher that routes calls to specialized child procedures based on parameter conditions, giving each child its own cached plan.

This is the approach that many SQL Server experts recommend for extreme parameter sniffing cases, but it is painful to maintain by hand. T-Lift generates the wrapper and all child procedures from a single annotated source.

Directives

--#wrapper                              Enable wrapper mode
--#branch <suffix> <condition>          Define a conditional child branch
--#branch-default <suffix>              Define the default fallback child

Example

CREATE OR ALTER PROCEDURE dbo.SearchCustomers
    @CustomerID INT = NULL,
    @City NVARCHAR(50) = NULL
AS
--#wrapper
--#branch _byCust @CustomerID IS NOT NULL
--#branch _byCity @City IS NOT NULL
--#branch-default _all
                                        --#[ CustSearch
SELECT c.CustomerID, c.FirstName, c.LastName, c.Email, c.City
FROM dbo.Customers c
WHERE                                   --#if @CustomerID IS NOT NULL OR @City IS NOT NULL
(                                       --#-
@CustomerID IS NULL OR                  --#-
c.CustomerID = @CustomerID              --#if @CustomerID IS NOT NULL
)                                       --#-
AND                                     --#if @CustomerID IS NOT NULL AND @City IS NOT NULL
(                                       --#-
@City IS NULL OR                        --#-
c.City = @City                          --#if @City IS NOT NULL
)                                       --#-
                                        --#]

T-Lift produces:

  1. A wrapper procedure (tlift_version_of_your_sproc) that dispatches:

    IF @CustomerID IS NOT NULL
        EXEC [dbo].[tlift_version_of_your_sproc_byCust] @CustomerID = @CustomerID, @City = @City;
    ELSE IF @City IS NOT NULL
        EXEC [dbo].[tlift_version_of_your_sproc_byCity] @CustomerID = @CustomerID, @City = @City;
    ELSE
        EXEC [dbo].[tlift_version_of_your_sproc_all] @CustomerID = @CustomerID, @City = @City;
  2. Child procedures (_byCust, _byCity, _all), each a full copy of the rendered dynamic SQL procedure with its own name. Each child gets its own plan cache entry.


Validation Mode

Before rendering, you can validate your annotated procedure for common mistakes:

EXEC dbo.sp_tlift
    @DatabaseName  = 'YourDatabase',
    @ProcedureName = 'YourProcedure',
    @validateOnly  = 1;

This checks for:

  • Procedure existence — does the target procedure actually exist?
  • Unmatched brackets — every --#[ needs a --#].
  • Unknown directives — catches typos like --#fi instead of --#if.
  • Out-of-section conditionals--#if used outside a --#[ / --#] block.
  • Unmatched usevar references--#usevar @x without a corresponding DECLARE @x ... --#var.

No output is produced — just error messages if anything is off.


Parameters

Parameter Type Default Description
@DatabaseName NVARCHAR(128) Target database containing the source procedure. Required.
@SchemaName NVARCHAR(128) 'dbo' Schema of the source procedure.
@ProcedureName NVARCHAR(128) Name of the source procedure. Required.
@ProcedureNameNew NVARCHAR(128) 'tlift_version_of_your_sproc' Name for the generated procedure.
@validateOnly BIT 0 Validate directives without rendering output.
@debugLevel INT 0 Controls debug output verbosity (0 = off).
@verboseMode BIT 0 Additional processing messages.
@includeOurComments BIT 0 Include T-Lift's own comments in the output.
@includeDebug BIT 1 Include debug-related markers in the output.
@help BIT 0 Print usage information and exit.
@Result NVARCHAR(MAX) OUTPUT The rendered procedure as a string.

Compatibility

  • Minimum SQL Server version: SQL Server 2017 (uses STRING_AGG, TRIM).
  • On SQL Server 2022+, T-Lift uses STRING_SPLIT with the enable_ordinal option for guaranteed line ordering. On older versions, it falls back to an identity-based approach.
  • T-Lift runs as a standard stored procedure — no CLR, no external dependencies.

Roadmap

There is plenty left to do. Among other things:

  • Automatic deployment option (@execute parameter to directly create the generated procedure)
  • Support for custom directive prefixes (currently # is hard-coded)
  • Extended validation and better error messages
  • Nested dynamic SQL sections

Feedback and contributions via GitHub issues are welcome.


Version Log

  • 1.01 — Named conditions (--#define), block removal (--#{- / --#-}), --#{if blocks inside dynamic SQL sections (empty line guard fix), improved condition handling in --#if / --#{if / --#{elseif with named condition resolution, unused condition warnings, removal block bracket validation
  • 1.00 — Else / else-if directives (--#else, --#{elseif), validation mode (@validateOnly), wrapper procedure generation (--#wrapper, --#branch), recompile hint (--#recompile), comment-out directive (--#c), bucket-based plan cache segmentation (--#buckets), unknown directive detection, bracket matching validation, TRY/CATCH error handling, safe procedure rename, SQL 2022+ ordinal support
  • 0.46 — Replaced sp_helptext with sys.sql_modules for procedure text retrieval. Added support for output parameters.
  • 0.43 — First public release on GitHub

License

Apache 2.0 — see LICENSE for details.

About

T-Lift is a T-SQL precompiler that lets developers use directive-based meta-code within stored procedures to generate controlled, dynamic T-SQL. It is designed for teams that understand when and why dynamic SQL helps SQL Server build more predictable execution plans.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • TSQL 100.0%