refactor(dedup): IQueryBreakdownCollectionView eliminates Markdown adapter classes
SonarQube Analysis / sonarqube (pull_request) Successful in 3m39s
SonarQube Analysis / sonarqube (pull_request) Successful in 3m39s
Replaces the per-dialect <c>Adapter</c> nested classes (which were themselves the leftover duplication after PR #22's first cut) with a shared <c>IQueryBreakdownCollectionView</c> interface implemented directly on each dialect's <c>QueryBreakdownCollection</c>. New foundation types in <c>Strata.SqlTools.Breakdowns.SqlServer</c>: - **<c>IQueryBreakdownCollectionView</c>** — dialect-neutral view exposing QueryCount, UniqueParameterCount, TotalSelectedColumns, UniqueTableCount, QueriesForReport (typed against the SqlServer <c>QueryBreakdown</c> base — PG/Snowflake satisfy via <c>IReadOnlyList</c> covariance), and ParameterUsageRecords. - **<c>ParameterUsageRecord</c>** — record type for per-parameter usage stats, projected from each dialect's <c>ParameterUsageReport</c>. The three dialect <c>QueryBreakdownCollection</c> classes now implement the interface explicitly — a handful of one-line forwarders per class. The Markdown layer's old <c>ICollectionMarkdownData</c> interface and the writer-internal <c>ParameterUsageRow</c> type are deleted; the template and writer take <c>IQueryBreakdownCollectionView</c> and <c>ParameterUsageRecord</c> directly. Net effect on the Markdown wrappers: - <c>Markdown.SqlServer.QueryBreakdownCollectionGenerator</c> loses its <c>Adapter</c> nested class and its 6 forwarders pass <c>collection</c> straight through. - <c>Markdown.PostgreSql.QueryBreakdownCollectionGenerator</c> ditto. - <c>Markdown.Snowflake.QueryBreakdownCollectionGenerator</c> migrated to the same pattern; its dialect-specific <c>GenerateSnowflakeFeaturesAnalysis</c> and feature-aware <c>QueryCompositionReport</c> callback stay intact (they still call <c>CollectionReportWriter</c> directly). Public API additions: <c>IQueryBreakdownCollectionView</c> and <c>ParameterUsageRecord</c> (both new, both opt-in). Public API removals: none — the dialect <c>ParameterUsageReport</c> classes are untouched and the dialect <c>QueryBreakdownCollectionGenerator</c> public surface is identical. All 1180 tests stay green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
4038b3dab5
commit
f4d318b35c
@@ -1,37 +1,39 @@
|
||||
using Strata.SqlTools.Breakdowns.SqlServer;
|
||||
|
||||
namespace Strata.SqlTools.Markdown.Common;
|
||||
|
||||
/// <summary>
|
||||
/// Shared method bodies for the per-dialect <c>QueryBreakdownCollectionGenerator</c>
|
||||
/// classes. Each dialect wraps its <c>QueryBreakdownCollection</c> in an
|
||||
/// <see cref="ICollectionMarkdownData"/> adapter and supplies a dialect-specific
|
||||
/// <see cref="MarkdownDialectFormat"/>; this template handles the rest.
|
||||
/// Shared method bodies for the per-dialect <c>QueryBreakdownCollectionGenerator</c> classes.
|
||||
/// Operates against the dialect-neutral <see cref="IQueryBreakdownCollectionView"/> contract
|
||||
/// that every dialect's <c>QueryBreakdownCollection</c> implements, so the dialect wrappers
|
||||
/// can pass their collection straight through with no per-dialect adapter required.
|
||||
/// </summary>
|
||||
internal static class CollectionMarkdownGenerator
|
||||
{
|
||||
public static string GenerateCollectionReport(ICollectionMarkdownData data, MarkdownDialectFormat format, string? title)
|
||||
public static string GenerateCollectionReport(IQueryBreakdownCollectionView view, MarkdownDialectFormat format, string? title)
|
||||
=> CollectionReportWriter.CollectionReport(title, new[]
|
||||
{
|
||||
GenerateCollectionSummary(data),
|
||||
GenerateParameterAnalysis(data, format),
|
||||
GenerateQueryCompositionReport(data, format)
|
||||
GenerateCollectionSummary(view),
|
||||
GenerateParameterAnalysis(view, format),
|
||||
GenerateQueryCompositionReport(view, format)
|
||||
});
|
||||
|
||||
public static string GenerateCollectionSummary(ICollectionMarkdownData data)
|
||||
public static string GenerateCollectionSummary(IQueryBreakdownCollectionView view)
|
||||
=> CollectionReportWriter.CollectionSummary(
|
||||
data.QueryCount,
|
||||
data.UniqueParameterCount,
|
||||
data.TotalSelectedColumns,
|
||||
data.UniqueTableCount);
|
||||
view.QueryCount,
|
||||
view.UniqueParameterCount,
|
||||
view.TotalSelectedColumns,
|
||||
view.UniqueTableCount);
|
||||
|
||||
public static string GenerateParameterAnalysis(ICollectionMarkdownData data, MarkdownDialectFormat format)
|
||||
=> CollectionReportWriter.ParameterAnalysis(data.ParameterRows.ToList(), data.QueriesForReport, format);
|
||||
public static string GenerateParameterAnalysis(IQueryBreakdownCollectionView view, MarkdownDialectFormat format)
|
||||
=> CollectionReportWriter.ParameterAnalysis(view.ParameterUsageRecords.ToList(), view.QueriesForReport, format);
|
||||
|
||||
public static string GenerateParameterDependencyDiagram(ICollectionMarkdownData data, MarkdownDialectFormat format)
|
||||
=> CollectionReportWriter.ParameterDependencyDiagram(data.QueriesForReport, format);
|
||||
public static string GenerateParameterDependencyDiagram(IQueryBreakdownCollectionView view, MarkdownDialectFormat format)
|
||||
=> CollectionReportWriter.ParameterDependencyDiagram(view.QueriesForReport, format);
|
||||
|
||||
public static string GenerateQueryCompositionReport(ICollectionMarkdownData data, MarkdownDialectFormat format)
|
||||
=> CollectionReportWriter.QueryCompositionReport(data.QueriesForReport, format);
|
||||
public static string GenerateQueryCompositionReport(IQueryBreakdownCollectionView view, MarkdownDialectFormat format)
|
||||
=> CollectionReportWriter.QueryCompositionReport(view.QueriesForReport, format);
|
||||
|
||||
public static string GenerateBatchFlowDiagram(ICollectionMarkdownData data, string? openLabel, string? closeLabel)
|
||||
=> CollectionReportWriter.BatchFlowDiagram(data.QueryCount, openLabel, closeLabel);
|
||||
public static string GenerateBatchFlowDiagram(IQueryBreakdownCollectionView view, string? openLabel, string? closeLabel)
|
||||
=> CollectionReportWriter.BatchFlowDiagram(view.QueryCount, openLabel, closeLabel);
|
||||
}
|
||||
|
||||
@@ -32,28 +32,6 @@ internal sealed class MarkdownDialectFormat
|
||||
public required bool IncludeHavingRow { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Carries the precomputed usage statistics for a single parameter, decoupling the writer from each
|
||||
/// dialect's concrete parameter-usage report type.
|
||||
/// </summary>
|
||||
internal sealed class ParameterUsageRow
|
||||
{
|
||||
/// <summary>The parameter name (without any dialect prefix).</summary>
|
||||
public required string ParameterName { get; init; }
|
||||
|
||||
/// <summary>Whether the parameter is used by every query in the collection.</summary>
|
||||
public required bool IsUsedInAllQueries { get; init; }
|
||||
|
||||
/// <summary>The number of queries that use the parameter.</summary>
|
||||
public required int UsedInQueryCount { get; init; }
|
||||
|
||||
/// <summary>The total number of queries in the collection.</summary>
|
||||
public required int TotalQueries { get; init; }
|
||||
|
||||
/// <summary>The parameter's last-seen value.</summary>
|
||||
public required object? Value { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the dialect-agnostic Markdown for query breakdown collection reports. The per-dialect
|
||||
/// generators supply a <see cref="MarkdownDialectFormat"/> and precomputed data; this writer produces
|
||||
@@ -113,7 +91,7 @@ internal static class CollectionReportWriter
|
||||
/// Renders the parameter analysis section, including the dependency diagram.
|
||||
/// </summary>
|
||||
public static string ParameterAnalysis(
|
||||
IReadOnlyList<ParameterUsageRow> parameters,
|
||||
IReadOnlyList<ParameterUsageRecord> parameters,
|
||||
IEnumerable<QueryBreakdown> queries,
|
||||
MarkdownDialectFormat format)
|
||||
{
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
using SqlServerBreakdowns = Strata.SqlTools.Breakdowns.SqlServer;
|
||||
|
||||
namespace Strata.SqlTools.Markdown.Common;
|
||||
|
||||
/// <summary>
|
||||
/// Dialect-neutral view of a <c>QueryBreakdownCollection</c> as seen by the Markdown
|
||||
/// generators. Each per-dialect <c>QueryBreakdownCollectionGenerator</c> wraps its
|
||||
/// dialect-specific collection in an implementation of this interface so the shared
|
||||
/// <see cref="CollectionMarkdownGenerator"/> template can operate uniformly.
|
||||
/// </summary>
|
||||
internal interface ICollectionMarkdownData
|
||||
{
|
||||
int QueryCount { get; }
|
||||
int UniqueParameterCount { get; }
|
||||
int TotalSelectedColumns { get; }
|
||||
int UniqueTableCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Queries as the base <see cref="SqlServerBreakdowns.QueryBreakdown"/> type. Used
|
||||
/// directly by <see cref="CollectionReportWriter.QueryCompositionReport"/>
|
||||
/// (which needs <see cref="IReadOnlyList{T}"/>) and via covariance by the other
|
||||
/// writer methods that accept <see cref="IEnumerable{T}"/>.
|
||||
/// </summary>
|
||||
IReadOnlyList<SqlServerBreakdowns.QueryBreakdown> QueriesForReport { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Parameter usage already mapped into the writer's dialect-agnostic row type.
|
||||
/// </summary>
|
||||
IEnumerable<ParameterUsageRow> ParameterRows { get; }
|
||||
}
|
||||
@@ -24,63 +24,41 @@ public static class QueryBreakdownCollectionGenerator
|
||||
/// Generates a comprehensive collection report in Markdown format with PostgreSQL-specific information.
|
||||
/// </summary>
|
||||
public static string GenerateCollectionReport(QueryBreakdownCollection collection, string? title = null)
|
||||
=> CollectionMarkdownGenerator.GenerateCollectionReport(Adapt(collection), Format, title);
|
||||
=> CollectionMarkdownGenerator.GenerateCollectionReport(collection, Format, title);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a summary section for the collection.
|
||||
/// </summary>
|
||||
public static string GenerateCollectionSummary(QueryBreakdownCollection collection)
|
||||
=> CollectionMarkdownGenerator.GenerateCollectionSummary(Adapt(collection));
|
||||
=> CollectionMarkdownGenerator.GenerateCollectionSummary(collection);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a parameter analysis report with PostgreSQL parameter syntax support.
|
||||
/// </summary>
|
||||
public static string GenerateParameterAnalysis(QueryBreakdownCollection collection)
|
||||
=> CollectionMarkdownGenerator.GenerateParameterAnalysis(Adapt(collection), Format);
|
||||
=> CollectionMarkdownGenerator.GenerateParameterAnalysis(collection, Format);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a Mermaid diagram showing parameter dependencies across queries.
|
||||
/// </summary>
|
||||
public static string GenerateParameterDependencyDiagram(QueryBreakdownCollection collection)
|
||||
=> CollectionMarkdownGenerator.GenerateParameterDependencyDiagram(Adapt(collection), Format);
|
||||
=> CollectionMarkdownGenerator.GenerateParameterDependencyDiagram(collection, Format);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a detailed query composition report.
|
||||
/// </summary>
|
||||
public static string GenerateQueryCompositionReport(QueryBreakdownCollection collection)
|
||||
=> CollectionMarkdownGenerator.GenerateQueryCompositionReport(Adapt(collection), Format);
|
||||
=> CollectionMarkdownGenerator.GenerateQueryCompositionReport(collection, Format);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a batch execution flow diagram for PostgreSQL.
|
||||
/// </summary>
|
||||
public static string GenerateBatchFlowDiagram(QueryBreakdownCollection collection, bool includeTransaction = false)
|
||||
=> CollectionMarkdownGenerator.GenerateBatchFlowDiagram(
|
||||
Adapt(collection),
|
||||
collection,
|
||||
includeTransaction ? "BEGIN" : null,
|
||||
includeTransaction ? "COMMIT" : 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<Breakdowns.SqlServer.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>
|
||||
/// Formats a parameter using PostgreSQL syntax: <c>$n</c> for positional, <c>:name</c> for named.
|
||||
/// </summary>
|
||||
|
||||
@@ -24,9 +24,6 @@ public static class QueryBreakdownCollectionGenerator
|
||||
/// <summary>
|
||||
/// Generates a comprehensive collection report in Markdown format with Snowflake-specific information.
|
||||
/// </summary>
|
||||
/// <param name="collection">The QueryBreakdownCollection to document.</param>
|
||||
/// <param name="title">Optional title for the report.</param>
|
||||
/// <returns>A string containing the Markdown documentation.</returns>
|
||||
public static string GenerateCollectionReport(QueryBreakdownCollection collection, string? title = null)
|
||||
=> CollectionReportWriter.CollectionReport(title, new[]
|
||||
{
|
||||
@@ -39,20 +36,12 @@ public static class QueryBreakdownCollectionGenerator
|
||||
/// <summary>
|
||||
/// Generates a summary section for the collection.
|
||||
/// </summary>
|
||||
/// <param name="collection">The QueryBreakdownCollection to summarize.</param>
|
||||
/// <returns>Markdown summary section.</returns>
|
||||
public static string GenerateCollectionSummary(QueryBreakdownCollection collection)
|
||||
=> CollectionReportWriter.CollectionSummary(
|
||||
collection.QueryBreakdowns.Count,
|
||||
collection.GetAllUniqueParameters().Count(),
|
||||
collection.GetTotalSelectedColumns(),
|
||||
collection.GetUniqueTableReferences().Count());
|
||||
=> CollectionMarkdownGenerator.GenerateCollectionSummary(collection);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a Snowflake-specific features analysis section.
|
||||
/// </summary>
|
||||
/// <param name="collection">The QueryBreakdownCollection to analyze.</param>
|
||||
/// <returns>Markdown Snowflake features section.</returns>
|
||||
public static string GenerateSnowflakeFeaturesAnalysis(QueryBreakdownCollection collection)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
@@ -73,24 +62,18 @@ public static class QueryBreakdownCollectionGenerator
|
||||
/// <summary>
|
||||
/// Generates a parameter analysis report with Snowflake parameter syntax support.
|
||||
/// </summary>
|
||||
/// <param name="collection">The QueryBreakdownCollection to analyze.</param>
|
||||
/// <returns>Markdown parameter analysis section.</returns>
|
||||
public static string GenerateParameterAnalysis(QueryBreakdownCollection collection)
|
||||
=> CollectionReportWriter.ParameterAnalysis(MapParameters(collection), collection.QueryBreakdowns, Format);
|
||||
=> CollectionMarkdownGenerator.GenerateParameterAnalysis(collection, Format);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a Mermaid diagram showing parameter dependencies across queries.
|
||||
/// </summary>
|
||||
/// <param name="collection">The QueryBreakdownCollection to visualize.</param>
|
||||
/// <returns>Mermaid diagram markdown.</returns>
|
||||
public static string GenerateParameterDependencyDiagram(QueryBreakdownCollection collection)
|
||||
=> CollectionReportWriter.ParameterDependencyDiagram(collection.QueryBreakdowns, Format);
|
||||
=> CollectionMarkdownGenerator.GenerateParameterDependencyDiagram(collection, Format);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a detailed query composition report with Snowflake-specific information.
|
||||
/// </summary>
|
||||
/// <param name="collection">The QueryBreakdownCollection to report on.</param>
|
||||
/// <returns>Markdown composition report section.</returns>
|
||||
public static string GenerateQueryCompositionReport(QueryBreakdownCollection collection)
|
||||
{
|
||||
var stageQueries = collection.WhereUseStageReference().ToList();
|
||||
@@ -105,30 +88,12 @@ public static class QueryBreakdownCollectionGenerator
|
||||
/// <summary>
|
||||
/// Generates a batch execution flow diagram for Snowflake.
|
||||
/// </summary>
|
||||
/// <param name="collection">The QueryBreakdownCollection to visualize.</param>
|
||||
/// <param name="includeSessionSetup">Whether to show session setup statements.</param>
|
||||
/// <returns>Mermaid diagram markdown.</returns>
|
||||
public static string GenerateBatchFlowDiagram(QueryBreakdownCollection collection, bool includeSessionSetup = false)
|
||||
=> CollectionReportWriter.BatchFlowDiagram(
|
||||
collection.QueryBreakdowns.Count,
|
||||
=> CollectionMarkdownGenerator.GenerateBatchFlowDiagram(
|
||||
collection,
|
||||
includeSessionSetup ? "Session Setup" : null,
|
||||
closeLabel: null);
|
||||
|
||||
/// <summary>
|
||||
/// Maps the collection's parameter usage report into the writer's dialect-agnostic rows.
|
||||
/// </summary>
|
||||
private static List<ParameterUsageRow> MapParameters(QueryBreakdownCollection collection)
|
||||
=> collection.GetParameterUsageReport()
|
||||
.Select(p => new ParameterUsageRow
|
||||
{
|
||||
ParameterName = p.ParameterName,
|
||||
IsUsedInAllQueries = p.IsUsedInAllQueries,
|
||||
UsedInQueryCount = p.UsedInQueryCount,
|
||||
TotalQueries = p.TotalQueries,
|
||||
Value = p.Value
|
||||
})
|
||||
.ToList();
|
||||
|
||||
/// <summary>
|
||||
/// Appends Snowflake-specific feature information for a query.
|
||||
/// </summary>
|
||||
|
||||
@@ -23,63 +23,41 @@ public static class QueryBreakdownCollectionGenerator
|
||||
/// Generates a comprehensive collection report in Markdown format.
|
||||
/// </summary>
|
||||
public static string GenerateCollectionReport(QueryBreakdownCollection collection, string? title = null)
|
||||
=> CollectionMarkdownGenerator.GenerateCollectionReport(Adapt(collection), Format, title);
|
||||
=> CollectionMarkdownGenerator.GenerateCollectionReport(collection, Format, title);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a summary section for the collection.
|
||||
/// </summary>
|
||||
public static string GenerateCollectionSummary(QueryBreakdownCollection collection)
|
||||
=> CollectionMarkdownGenerator.GenerateCollectionSummary(Adapt(collection));
|
||||
=> CollectionMarkdownGenerator.GenerateCollectionSummary(collection);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a parameter analysis report.
|
||||
/// </summary>
|
||||
public static string GenerateParameterAnalysis(QueryBreakdownCollection collection)
|
||||
=> CollectionMarkdownGenerator.GenerateParameterAnalysis(Adapt(collection), Format);
|
||||
=> CollectionMarkdownGenerator.GenerateParameterAnalysis(collection, Format);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a Mermaid diagram showing parameter dependencies across queries.
|
||||
/// </summary>
|
||||
public static string GenerateParameterDependencyDiagram(QueryBreakdownCollection collection)
|
||||
=> CollectionMarkdownGenerator.GenerateParameterDependencyDiagram(Adapt(collection), Format);
|
||||
=> CollectionMarkdownGenerator.GenerateParameterDependencyDiagram(collection, Format);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a detailed query composition report.
|
||||
/// </summary>
|
||||
public static string GenerateQueryCompositionReport(QueryBreakdownCollection collection)
|
||||
=> CollectionMarkdownGenerator.GenerateQueryCompositionReport(Adapt(collection), Format);
|
||||
=> CollectionMarkdownGenerator.GenerateQueryCompositionReport(collection, Format);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a batch execution flow diagram.
|
||||
/// </summary>
|
||||
public static string GenerateBatchFlowDiagram(QueryBreakdownCollection collection, bool includeTransaction = false)
|
||||
=> CollectionMarkdownGenerator.GenerateBatchFlowDiagram(
|
||||
Adapt(collection),
|
||||
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>
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Strata.SqlTools.Breakdowns.PostgreSql;
|
||||
/// including support for PostgreSQL features like schema-qualified identifiers,
|
||||
/// LIMIT/OFFSET clauses, parameterized queries using $1, $2 syntax, and CTEs.
|
||||
/// </remarks>
|
||||
public class QueryBreakdownCollection : SqlBreakdownCollection
|
||||
public class QueryBreakdownCollection : SqlBreakdownCollection, SqlServer.IQueryBreakdownCollectionView
|
||||
{
|
||||
private readonly List<QueryBreakdown> _queryBreakdowns;
|
||||
|
||||
@@ -199,6 +199,17 @@ public class QueryBreakdownCollection : SqlBreakdownCollection
|
||||
TotalQueries = usage.TotalQueries
|
||||
});
|
||||
}
|
||||
|
||||
// --- IQueryBreakdownCollectionView ---
|
||||
|
||||
int SqlServer.IQueryBreakdownCollectionView.QueryCount => QueryBreakdowns.Count;
|
||||
int SqlServer.IQueryBreakdownCollectionView.UniqueParameterCount => GetAllUniqueParameters().Count();
|
||||
int SqlServer.IQueryBreakdownCollectionView.TotalSelectedColumns => GetTotalSelectedColumns();
|
||||
int SqlServer.IQueryBreakdownCollectionView.UniqueTableCount => GetUniqueTableReferences().Count();
|
||||
IReadOnlyList<SqlServer.QueryBreakdown> SqlServer.IQueryBreakdownCollectionView.QueriesForReport => QueryBreakdowns;
|
||||
IEnumerable<SqlServer.ParameterUsageRecord> SqlServer.IQueryBreakdownCollectionView.ParameterUsageRecords
|
||||
=> GetParameterUsageReport().Select(p => new SqlServer.ParameterUsageRecord(
|
||||
p.ParameterName, p.Value, p.UsedInQueryCount, p.TotalQueries, p.IsUsedInAllQueries));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Strata.SqlTools.Breakdowns.Snowflake;
|
||||
/// time travel, snowflake-specific parameters (:parameter and @parameter syntax),
|
||||
/// and proper batch handling.
|
||||
/// </remarks>
|
||||
public class QueryBreakdownCollection : SqlServer.QueryBreakdownCollectionBase<QueryBreakdown>
|
||||
public class QueryBreakdownCollection : SqlServer.QueryBreakdownCollectionBase<QueryBreakdown>, SqlServer.IQueryBreakdownCollectionView
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="QueryBreakdownCollection"/> class for Snowflake.
|
||||
@@ -406,6 +406,17 @@ public class QueryBreakdownCollection : SqlServer.QueryBreakdownCollectionBase<Q
|
||||
});
|
||||
}
|
||||
|
||||
// --- IQueryBreakdownCollectionView ---
|
||||
|
||||
int SqlServer.IQueryBreakdownCollectionView.QueryCount => QueryBreakdowns.Count;
|
||||
int SqlServer.IQueryBreakdownCollectionView.UniqueParameterCount => GetAllUniqueParameters().Count();
|
||||
int SqlServer.IQueryBreakdownCollectionView.TotalSelectedColumns => GetTotalSelectedColumns();
|
||||
int SqlServer.IQueryBreakdownCollectionView.UniqueTableCount => GetUniqueTableReferences().Count();
|
||||
IReadOnlyList<SqlServer.QueryBreakdown> SqlServer.IQueryBreakdownCollectionView.QueriesForReport => QueryBreakdowns;
|
||||
IEnumerable<SqlServer.ParameterUsageRecord> SqlServer.IQueryBreakdownCollectionView.ParameterUsageRecords
|
||||
=> GetParameterUsageReport().Select(p => new SqlServer.ParameterUsageRecord(
|
||||
p.ParameterName, p.Value, p.UsedInQueryCount, p.TotalQueries, p.IsUsedInAllQueries));
|
||||
|
||||
/// <summary>
|
||||
/// Gets a summary of all queries including their types and basic composition.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
namespace Strata.SqlTools.Breakdowns.SqlServer;
|
||||
|
||||
/// <summary>
|
||||
/// Dialect-neutral view of a query breakdown collection. Exposes the metrics and the per-query
|
||||
/// access surface that the Markdown report generators need — implemented by each dialect's
|
||||
/// <c>QueryBreakdownCollection</c> so the Markdown layer can operate without dialect-specific
|
||||
/// adapters.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="QueriesForReport"/> is typed against the SqlServer <see cref="QueryBreakdown"/>
|
||||
/// base; PostgreSQL and Snowflake collections satisfy this via <see cref="IReadOnlyList{T}"/>
|
||||
/// covariance because their dialect-specific <c>QueryBreakdown</c> classes derive from this one.
|
||||
/// </remarks>
|
||||
public interface IQueryBreakdownCollectionView
|
||||
{
|
||||
/// <summary>Number of queries in the collection.</summary>
|
||||
int QueryCount { get; }
|
||||
|
||||
/// <summary>Number of unique parameter names across all queries.</summary>
|
||||
int UniqueParameterCount { get; }
|
||||
|
||||
/// <summary>Number of columns selected across all queries.</summary>
|
||||
int TotalSelectedColumns { get; }
|
||||
|
||||
/// <summary>Number of distinct table references across all queries.</summary>
|
||||
int UniqueTableCount { get; }
|
||||
|
||||
/// <summary>The queries, as the shared <see cref="QueryBreakdown"/> base type.</summary>
|
||||
IReadOnlyList<QueryBreakdown> QueriesForReport { get; }
|
||||
|
||||
/// <summary>Per-parameter usage records, mapped to the dialect-neutral
|
||||
/// <see cref="ParameterUsageRecord"/> type.</summary>
|
||||
IEnumerable<ParameterUsageRecord> ParameterUsageRecords { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dialect-neutral, immutable record describing how often a parameter is used across the queries
|
||||
/// in a collection. Each dialect's <c>ParameterUsageReport</c> projects into this type so the
|
||||
/// Markdown layer can present usage tables without knowing about dialect-specific shapes.
|
||||
/// </summary>
|
||||
/// <param name="ParameterName">The parameter name (no dialect prefix).</param>
|
||||
/// <param name="Value">The parameter's last-seen value.</param>
|
||||
/// <param name="UsedInQueryCount">How many queries reference this parameter.</param>
|
||||
/// <param name="TotalQueries">Total queries in the collection.</param>
|
||||
/// <param name="IsUsedInAllQueries">Whether every query uses the parameter.</param>
|
||||
public sealed record ParameterUsageRecord(
|
||||
string ParameterName,
|
||||
object? Value,
|
||||
int UsedInQueryCount,
|
||||
int TotalQueries,
|
||||
bool IsUsedInAllQueries);
|
||||
@@ -9,7 +9,7 @@ namespace Strata.SqlTools.Breakdowns.SqlServer;
|
||||
/// This class extends SqlBreakdownCollection with SQL Server-specific functionality,
|
||||
/// including support for T-SQL features like batches (GO), temporary tables, stored procedures, and CTEs.
|
||||
/// </remarks>
|
||||
public class QueryBreakdownCollection : QueryBreakdownCollectionBase<QueryBreakdown>
|
||||
public class QueryBreakdownCollection : QueryBreakdownCollectionBase<QueryBreakdown>, IQueryBreakdownCollectionView
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="QueryBreakdownCollection"/> class.
|
||||
@@ -187,6 +187,17 @@ public class QueryBreakdownCollection : QueryBreakdownCollectionBase<QueryBreakd
|
||||
});
|
||||
}
|
||||
|
||||
// --- IQueryBreakdownCollectionView ---
|
||||
|
||||
int IQueryBreakdownCollectionView.QueryCount => QueryBreakdowns.Count;
|
||||
int IQueryBreakdownCollectionView.UniqueParameterCount => GetAllUniqueParameters().Count();
|
||||
int IQueryBreakdownCollectionView.TotalSelectedColumns => GetTotalSelectedColumns();
|
||||
int IQueryBreakdownCollectionView.UniqueTableCount => GetUniqueTableReferences().Count();
|
||||
IReadOnlyList<QueryBreakdown> IQueryBreakdownCollectionView.QueriesForReport => QueryBreakdowns;
|
||||
IEnumerable<ParameterUsageRecord> IQueryBreakdownCollectionView.ParameterUsageRecords
|
||||
=> GetParameterUsageReport().Select(p => new ParameterUsageRecord(
|
||||
p.ParameterName, p.Value, p.UsedInQueryCount, p.TotalQueries, p.IsUsedInAllQueries));
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to get SQL Server data type from a .NET object.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user