SonarQube Analysis / sonarqube (pull_request) Successful in 3m42s
Final cluster Sonar was reporting: the 82-line copy-paste between `Markdown.SqlServer.QueryBreakdownCollectionGenerator` and `Markdown.PostgreSql.QueryBreakdownCollectionGenerator`. Both classes existed because each dialect has a different concrete `QueryBreakdownCollection` type with its own `ParameterUsageReport` class — no shared base for the methods to operate on. Resolves it with an adapter pattern in `Markdown.Common`: - **`ICollectionMarkdownData`** (new, internal): dialect-neutral view exposing query count, parameter / column / table totals, queries- for-report list, and parameter-rows (already-mapped to the writer's `ParameterUsageRow` type). - **`CollectionMarkdownGenerator`** (new, internal static): single template that takes the data + `MarkdownDialectFormat` and routes through `CollectionReportWriter`. The six `GenerateX` methods that were duplicated three times now live here once. - **SqlServer / PostgreSql wrappers**: shrunk to a `Format` static, a thin one-line forwarder per public method, and a private sealed `Adapter : ICollectionMarkdownData` nested class that does the dialect-specific extraction (including the `ParameterUsageReport → ParameterUsageRow` mapping that was previously duplicated three times as `MapParameters`). Public API unchanged — the existing `Markdown.SqlServer.QueryBreakdownCollectionGenerator.GenerateCollectionReport(collection, title)` etc. continue to work as before; their bodies just delegate. The three dialect-specific `ParameterUsageReport` classes are deliberately *not* unified yet — their `ToString()` overrides differ meaningfully per dialect and unifying would be a separate API discussion. Snowflake wrapper not touched in this commit — Sonar didn't flag it (its `GenerateSnowflakeFeaturesAnalysis` and feature-aware `QueryCompositionReport` callback make it structurally distinct). Consistency follow-up could move it onto the same adapter pattern without behavior change. All 1180 tests stay green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
105 lines
4.2 KiB
C#
105 lines
4.2 KiB
C#
using Strata.SqlTools.Breakdowns.SqlServer;
|
|
using Strata.SqlTools.Markdown.Common;
|
|
|
|
namespace Strata.SqlTools.Markdown.SqlServer;
|
|
|
|
/// <summary>
|
|
/// Generates Markdown documentation from QueryBreakdownCollection objects.
|
|
/// Creates comprehensive reports including collection summaries, parameter analysis, and batch flow visualization.
|
|
/// </summary>
|
|
public static class QueryBreakdownCollectionGenerator
|
|
{
|
|
private static readonly MarkdownDialectFormat Format = new()
|
|
{
|
|
ParameterTableLabel = name => $"@{name}",
|
|
ParameterNodeLabel = name => $"@{name}",
|
|
ParameterTypeName = GetParameterType,
|
|
ParameterNodeFill = "#e1f5ff",
|
|
QueryNodeFill = "#f3e5f5",
|
|
IncludeHavingRow = true
|
|
};
|
|
|
|
/// <summary>
|
|
/// Generates a comprehensive collection report in Markdown format.
|
|
/// </summary>
|
|
public static string GenerateCollectionReport(QueryBreakdownCollection collection, string? title = null)
|
|
=> CollectionMarkdownGenerator.GenerateCollectionReport(Adapt(collection), Format, title);
|
|
|
|
/// <summary>
|
|
/// Generates a summary section for the collection.
|
|
/// </summary>
|
|
public static string GenerateCollectionSummary(QueryBreakdownCollection collection)
|
|
=> CollectionMarkdownGenerator.GenerateCollectionSummary(Adapt(collection));
|
|
|
|
/// <summary>
|
|
/// Generates a parameter analysis report.
|
|
/// </summary>
|
|
public static string GenerateParameterAnalysis(QueryBreakdownCollection collection)
|
|
=> CollectionMarkdownGenerator.GenerateParameterAnalysis(Adapt(collection), Format);
|
|
|
|
/// <summary>
|
|
/// Generates a Mermaid diagram showing parameter dependencies across queries.
|
|
/// </summary>
|
|
public static string GenerateParameterDependencyDiagram(QueryBreakdownCollection collection)
|
|
=> CollectionMarkdownGenerator.GenerateParameterDependencyDiagram(Adapt(collection), Format);
|
|
|
|
/// <summary>
|
|
/// Generates a detailed query composition report.
|
|
/// </summary>
|
|
public static string GenerateQueryCompositionReport(QueryBreakdownCollection collection)
|
|
=> CollectionMarkdownGenerator.GenerateQueryCompositionReport(Adapt(collection), Format);
|
|
|
|
/// <summary>
|
|
/// Generates a batch execution flow diagram.
|
|
/// </summary>
|
|
public static string GenerateBatchFlowDiagram(QueryBreakdownCollection collection, bool includeTransaction = false)
|
|
=> CollectionMarkdownGenerator.GenerateBatchFlowDiagram(
|
|
Adapt(collection),
|
|
includeTransaction ? "BEGIN TRANSACTION" : null,
|
|
includeTransaction ? "COMMIT TRANSACTION" : null);
|
|
|
|
private static ICollectionMarkdownData Adapt(QueryBreakdownCollection collection) => new Adapter(collection);
|
|
|
|
private sealed class Adapter : ICollectionMarkdownData
|
|
{
|
|
private readonly QueryBreakdownCollection _c;
|
|
public Adapter(QueryBreakdownCollection c) { _c = c; }
|
|
public int QueryCount => _c.QueryBreakdowns.Count;
|
|
public int UniqueParameterCount => _c.GetAllUniqueParameters().Count();
|
|
public int TotalSelectedColumns => _c.GetTotalSelectedColumns();
|
|
public int UniqueTableCount => _c.GetUniqueTableReferences().Count();
|
|
public IReadOnlyList<QueryBreakdown> QueriesForReport => _c.QueryBreakdowns;
|
|
public IEnumerable<ParameterUsageRow> ParameterRows
|
|
=> _c.GetParameterUsageReport().Select(p => new ParameterUsageRow
|
|
{
|
|
ParameterName = p.ParameterName,
|
|
IsUsedInAllQueries = p.IsUsedInAllQueries,
|
|
UsedInQueryCount = p.UsedInQueryCount,
|
|
TotalQueries = p.TotalQueries,
|
|
Value = p.Value
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the parameter type name from a parameter value.
|
|
/// </summary>
|
|
private static string GetParameterType(object? value)
|
|
{
|
|
return value switch
|
|
{
|
|
null => "NULL",
|
|
bool => "BIT",
|
|
byte => "TINYINT",
|
|
short => "SMALLINT",
|
|
int => "INT",
|
|
long => "BIGINT",
|
|
float => "REAL",
|
|
double => "FLOAT",
|
|
decimal => "DECIMAL",
|
|
string => "NVARCHAR",
|
|
DateTime => "DATETIME2",
|
|
_ => "VARIANT"
|
|
};
|
|
}
|
|
}
|