Files
sql-utilities/src/Strata.SqlTools.Markdown/LinqToSql/SqlStatementGenerator.cs
T
Thom LambandClaude Opus 4.7 84b06557e5 chore(sonar)!: mark instance-data-free members static (CA1822)
Applied via `dotnet format analyzers --diagnostics CA1822 --severity info`.
12 files touched. The fixer also updated internal callers in tests to use
the type-name form (e.g. `gen.Method(x)` -> `Generator.Method(x)`); build
and full test suite remain green.

BREAKING CHANGE: two public methods become static and therefore can no
longer be invoked through an instance reference by external consumers:
- Strata.SqlTools.Markdown.LinqToSql.QueryBreakdownGenerator.GenerateMethodChainDiagram
- Strata.SqlTools.Markdown.LinqToSql.SqlStatementGenerator.GenerateLinqPipelineDiagram

Both are stateless utility methods on Generator classes — the static form
is the correct shape; the only callers in this repo already used the
type-name form. External code should change `gen.GenerateMethodChainDiagram(...)`
to `QueryBreakdownGenerator.GenerateMethodChainDiagram(...)`.

All other CA1822 hits in this commit are on private/protected members
(no public-surface impact).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 15:41:46 -05:00

117 lines
4.5 KiB
C#

using Strata.SqlTools.SqlBreakdown.Interfaces;
using Strata.SqlTools.SqlBreakdown.Interfaces.QueryEngine;
namespace Strata.SqlTools.Markdown.LinqToSql;
/// <summary>
/// Generates Mermaid diagrams for LINQ to SQL statements, including sequence diagrams
/// for statement execution flow and entity-relationship diagrams.
/// </summary>
public class SqlStatementGenerator
{
private readonly SqlServer.SqlStatementGenerator _baseGenerator;
/// <summary>
/// Initializes a new instance of the SqlStatementGenerator class.
/// </summary>
public SqlStatementGenerator()
{
_baseGenerator = new SqlServer.SqlStatementGenerator();
}
/// <summary>
/// Generates a Mermaid sequence diagram showing LINQ to SQL statement execution flow.
/// </summary>
/// <param name="sqlBreakdown">The LINQ to SQL breakdown object.</param>
/// <param name="title">Optional title for the diagram.</param>
/// <returns>A string containing the Mermaid sequence diagram markdown.</returns>
public string GenerateSequenceDiagram(ISqlBreakdown sqlBreakdown, string? title = null)
{
return _baseGenerator.GenerateSequenceDiagram(sqlBreakdown, title);
}
/// <summary>
/// Generates a Mermaid entity-relationship diagram from a SQL breakdown.
/// </summary>
/// <param name="sqlBreakdown">The SQL breakdown containing query information.</param>
/// <param name="title">Optional title for the diagram.</param>
/// <returns>A string containing the Mermaid ER diagram markdown.</returns>
public string GenerateEntityRelationshipDiagram(ISqlBreakdown sqlBreakdown, string? title = null)
{
//Extract table names from breakdown - just use FROM clause for now
var queryBreakdown = sqlBreakdown as IQueryBreakdown;
var tableNames = new List<string>();
var fromClauseText = queryBreakdown?.FromClause?.ToString();
if (!string.IsNullOrWhiteSpace(fromClauseText))
{
tableNames.Add(fromClauseText);
}
return _baseGenerator.GenerateEntityRelationshipDiagram(tableNames, title);
}
/// <summary>
/// Generates a diagram showing LINQ execution pipeline from a SQL breakdown.
/// </summary>
/// <param name="queryBreakdown">The query breakdown containing query information.</param>
/// <param name="title">Optional title for the diagram.</param>
/// <returns>A string containing the Mermaid diagram markdown.</returns>
public static string GenerateLinqPipelineDiagram(IQueryBreakdown queryBreakdown, string? title = null)
{
var sb = new System.Text.StringBuilder();
if (!string.IsNullOrWhiteSpace(title))
{
sb.AppendLine($"### {title}");
sb.AppendLine();
}
sb.AppendLine("```mermaid");
sb.AppendLine("sequenceDiagram");
sb.AppendLine(" participant Client as Client Application");
sb.AppendLine(" participant LINQ as LINQ Provider");
sb.AppendLine(" participant ET as Expression Tree");
sb.AppendLine(" participant SQL as SQL Generator");
sb.AppendLine(" participant DB as Database");
sb.AppendLine();
sb.AppendLine(" Client->>LINQ: LINQ Query");
sb.AppendLine(" activate LINQ");
// Check if there's a WHERE clause
var whereClause = queryBreakdown.WhereClause?.Clause;
if (!string.IsNullOrWhiteSpace(whereClause))
{
sb.AppendLine(" LINQ->>ET: Where Predicate");
sb.AppendLine(" activate ET");
}
// Check if there's a custom SELECT
var selectClause = queryBreakdown.SelectClause?.Clause;
if (!string.IsNullOrWhiteSpace(selectClause) && selectClause.Trim() != "*")
{
sb.AppendLine(" LINQ->>ET: Select Projection");
if (string.IsNullOrWhiteSpace(whereClause))
{
sb.AppendLine(" activate ET");
}
}
sb.AppendLine(" ET->>SQL: Expression Tree");
sb.AppendLine(" deactivate ET");
sb.AppendLine(" SQL->>DB: Generate SQL");
sb.AppendLine(" activate DB");
sb.AppendLine(" DB-->>SQL: Result Set");
sb.AppendLine(" deactivate DB");
sb.AppendLine(" SQL-->>LINQ: Mapped Objects");
sb.AppendLine(" LINQ-->>Client: IEnumerable Result");
sb.AppendLine(" deactivate LINQ");
sb.AppendLine("```");
sb.AppendLine();
return sb.ToString();
}
}