Releases: stevehansen/sql-inliner
2.4.1
New Features
-
DerivedTableStripper — New post-processing step that recursively strips unused columns and LEFT OUTER JOINs inside nested derived tables produced by inlining. Runs after inlining when
--strip-unused-columnsor--strip-unused-joinsis enabled. Iterates until no more stripping occurs to handle cascading effects across nesting levels. -
validatecommand — Batch-validates all views in a database. Phase 1 inlines every view and reports errors; Phase 2 (with--deploy) deploys and runs COUNT + EXCEPT comparisons. Supports--deploy-onlyfor fast SQL error checking,--filter(exact or SQL LIKE%wildcard),--output-dir,--stop-on-error, and--timeout. -
verifycommand — Auto-detects already-deployed inlined views (identified byBeginOriginal/EndOriginalmarkers) and validates them against their originals using COUNT + EXCEPT comparisons. Supports--filter,--stop-on-error, and--timeout. -
Two-phase
analyze— New--generate-scriptflag emits a self-contained SQL Server stored procedure for offline data extraction. The exported JSON can then be analyzed without a live database connection using--from-file. Useful for environments with restricted direct database access. -
Cross-platform credential store — Store connection string credentials securely per-platform: Windows Credential Manager, macOS Keychain, and Linux
secret-tool(libsecret). Managed via thecredentialssubcommand (add,list,remove).
Bug Fixes
-
Fix
SelectStarExpressionhandling —SELECT *andSELECT alias.*were not recognized as column references during column stripping and schema normalization, causing incorrect stripping of inner view columns. -
Fix flattener/stripper/inliner bugs — Resolved a set of cascading issues that caused validation errors on complex view chains. Reduced validate errors from 36 to 0 on a 486-view database.
-
Fix validate timeout/row count messaging — COUNT on the inlined view now runs first so row counts appear in timeout messages; summary details show correct inlined row counts.
Security
- Parameterized queries —
DatabaseConnectionnow uses parameterized queries via Dapper to prevent SQL injection when queryingsys.views. Previously, view names were interpolated directly into query strings.
Patch (2.4.0 → 2.4.1)
- Fix
net472/netstandard2.0build —DerivedTableFlattenerusedDictionary.GetValueOrDefault()andKeyValuePairtuple deconstruction, both of which are unavailable innet472andnetstandard2.0. The NuGet library package failed to build in 2.4.0; 2.4.1 fixes both. The CLI (net8.0) was unaffected.
2.3.0
Bug fix
- Fix column alias loss during derived table flattening — When a view was flattened inside a GROUP BY query, column references like
v.CompanyIdwere rewritten to their inner expression (e.g.,Companies_1.Id), silently changing the inferred column name fromCompanyIdtoId. Outer queries referencing the original name (e.g.,cl.CompanyId) would then fail with "Invalid column name". The fix snapshots inferred SELECT column names before rewriting and restores them as explicitASaliases when the last identifier changes.
2.2.0
What's New
Features
- Derived table flattening — New
FlattenDerivedTablesoption that removes unnecessary subquery wrappers after inlining- Phase 1: Single-table inner queries
- Phase 2: Multi-table (JOIN) inner queries
- Preserves derived table aliases on flattened single-table queries
- JSON config file — New
sqlinliner.jsonconfig file support with--configoption - Join stripping for derived tables — Extended join stripping to handle inline subqueries
- Persisted options — InlinerOptions stored in metadata comment and restored in optimize wizard
- Benchmark improvements — HTML benchmark report, per-table IO breakdown, execution plan capture
Bug Fixes
- Fix benchmark returning 0ms by flushing TDS messages and forcing English locale
- Add warmup run before benchmark for fair cache comparison
- Traverse UnqualifiedJoin (CROSS/OUTER APPLY) subtrees in flattener
- Merge inner WHERE into JOIN ON clause instead of outer WHERE
- Rewrite GROUP BY/HAVING refs and qualify unqualified columns in flattener
- Resolve nullable compiler warnings in DatabaseConnection
- Apply config file options as defaults in the optimize wizard
- Wire FlattenDerivedTables into the optimize wizard
- Fix no-args crash
2.1.0
New feature: Interactive optimization wizard
The new sqlinliner optimize subcommand provides a guided, interactive workflow for optimizing a view against a backup or development database. It walks you through the full troubleshooting cycle in one session:
- Connect to a backup DB (with prominent safety warning)
- Select a view and see metadata (SQL length, nested view count)
- Inline the view with the current options
- Review the generated SQL in your default editor (detects manual edits)
- Deploy as
[schema].[ViewName_Inlined]viaCREATE OR ALTER VIEW - Validate correctness with
COUNTandEXCEPTcomparisons - Iterate — toggle strip-joins / aggressive mode and re-inline
- Benchmark — compare CPU time, elapsed time, and logical reads (
SET STATISTICS TIME/IO) - Summary — session directory with all iterations, recommended SQL, and a printed (never executed)
DROP VIEWcleanup statement
sqlinliner optimize \
-cs "Server=.;Database=TestBackup;Integrated Security=true" \
-vn "dbo.VHeavy"New features
- Auto-strip outer joins whose columns are only referenced in their own ON clause —
LEFT/RIGHT/FULL OUTER JOINs are now automatically stripped when the joined table contributes no columns outside its join condition (no need for--aggressive-join-stripping). @join:uniqueand@join:requiredhints — annotate JOINs in your SQL to enable safe join removal forLEFT JOIN(with@join:unique) andINNER JOIN(with@join:unique @join:required).
Other changes
- Overhauled README and CLI
--helpwith comprehensive feature documentation - Updated
Microsoft.NET.Test.Sdkto 18.3.0
2.0.3
Fix
- Aggressive join stripping (stripping joins where the table is only referenced in its own ON clause) is now opt-in via
--aggressive-join-stripping. The previous default could incorrectly strip INNER JOINs with filter conditions in the ON clause, producing more rows than expected.
New option
--aggressive-join-strippingCLI flag /AggressiveJoinStrippingonInlinerOptions— enables the more aggressive join-condition exclusion logic. Use with caution as it can change results for INNER JOINs.
2.0.2
Fix
- Restore implicit alias assignment for views in subquery scopes. Views referenced multiple times across different subqueries (e.g. in OUTER APPLY) no longer fail with "Use of tables without using an alias" errors.
Tests
- Add regression test for same view in multiple subquery scopes
- Add join stripping tests for both implicit and explicit alias cases
2.0.1
Fix
- Publish both dotnet tool (
SqlInliner) and library (SqlInliner.Library) NuGet packages. The library package was incorrectly marked as a DotnetTool, preventing it from being referenced by projects.
2.0.0
What's new
Features
- Package as dotnet tool (
dotnet tool install -g SqlInliner) - Add file output and logging options
- Convert tests to use Shouldly and improve view inlining logic
Bug fixes
- Strip unused joins with multiple ON conditions (e.g.
INNER JOIN b ON a.BId = b.Id AND b.Type = 'B'now correctly strips whenbis unused elsewhere) - Update Program.cs for System.CommandLine 2.0.3 stable API
Infrastructure
- Switch NuGet publishing to OIDC trusted publishing
- Add osx-arm64 build target
- Drop EOL framework targets (netcoreapp3.1, net6.0), add net9.0 and net10.0
- Updated dependencies (DacFx, Dapper, MinVer, ThisAssembly, and more)
- Added 62+ unit tests covering core functionality
v1.0.0
Updated packages and switched to .NET 6.0
0.4.0-alpha
Added target frameworks net472 and netcoreapp3.1 - Added missing comments - Fixed compile error on netstandard2.0