refactor(breakdowns): Extract shared collection analysis logic
SonarQube Analysis / sonarqube (pull_request) Successful in 3m12s

This commit is contained in:
Thom Lamb
2026-05-21 13:45:46 -05:00
parent b7a8405e0d
commit a43be2639e
4 changed files with 280 additions and 436 deletions
@@ -257,12 +257,7 @@ public class QueryBreakdownCollection : SqlBreakdownCollection
/// </summary>
/// <returns>Total column count.</returns>
public int GetTotalSelectedColumns()
{
return _queryBreakdowns.Sum(q =>
!string.IsNullOrWhiteSpace(q.SelectClause?.Clause)
? q.SelectClause.Clause.Split(',').Length
: 0);
}
=> QueryCollectionAnalysisHelper.GetTotalSelectedColumns(_queryBreakdowns);
/// <summary>
/// Gets all unique table names referenced across all queries.
@@ -274,72 +269,14 @@ public class QueryBreakdownCollection : SqlBreakdownCollection
/// </remarks>
/// <returns>List of unique table names.</returns>
public IEnumerable<string> GetUniqueTableReferences()
{
var tables = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var tableNames = _queryBreakdowns
.Where(q => !string.IsNullOrWhiteSpace(q.FromClause?.Clause))
.SelectMany(q => ExtractTableNames(q.FromClause!.Clause!));
foreach (var table in tableNames)
{
tables.Add(table);
}
return tables;
}
=> QueryCollectionAnalysisHelper.GetUniqueTableReferences(_queryBreakdowns);
/// <summary>
/// Gets a summary of all queries including their types and basic composition.
/// </summary>
/// <returns>Summary information for each query.</returns>
public IEnumerable<QuerySummary> GetQuerySummaries()
{
return _queryBreakdowns.Select((q, index) => new QuerySummary
{
Index = index,
HasSelectClause = !string.IsNullOrWhiteSpace(q.SelectClause?.Clause),
HasFromClause = !string.IsNullOrWhiteSpace(q.FromClause?.Clause),
HasWhereClause = !string.IsNullOrWhiteSpace(q.WhereClause?.Clause),
HasGroupByClause = !string.IsNullOrWhiteSpace(q.GroupByClause?.Clause),
HasHavingClause = !string.IsNullOrWhiteSpace(q.HavingClause?.Clause),
HasOrderByClause = !string.IsNullOrWhiteSpace(q.OrderByClause?.Clause),
HasJoins = false,
HasCTE = q.WithClauses.Count > 0,
ColumnCount = !string.IsNullOrWhiteSpace(q.SelectClause?.Clause) ? q.SelectClause.Clause.Split(',').Length : 0,
ParameterCount = q.ParameterList.Count(),
JoinCount = 0
});
}
/// <summary>
/// Helper method to extract table names from a FROM clause.
/// </summary>
private static IEnumerable<string> ExtractTableNames(string fromClause)
{
if (string.IsNullOrWhiteSpace(fromClause))
{
yield break;
}
// Simple extraction: split by comma and clean up aliases
var parts = fromClause.Split(',');
foreach (var part in parts)
{
var trimmed = part.Trim();
// Remove alias (assuming format: table AS alias or table alias)
var tokens = trimmed.Split(new[] { " AS ", " " }, StringSplitOptions.RemoveEmptyEntries);
if (tokens.Length > 0)
{
var tableName = tokens[0].Trim();
if (!string.IsNullOrWhiteSpace(tableName))
{
yield return tableName;
}
}
}
}
=> QueryCollectionAnalysisHelper.GetQuerySummaries(_queryBreakdowns);
/// <summary>
/// Synchronizes parameters across all queries in the collection.
@@ -350,44 +287,7 @@ public class QueryBreakdownCollection : SqlBreakdownCollection
/// Only synchronizes parameters that the query already defines to avoid adding unused parameters.
/// </remarks>
public void SynchronizeParameters()
{
// Get all unique parameter names across all queries
var allParameterNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var query in _queryBreakdowns)
{
foreach (var paramName in query.Parameters.Keys)
{
allParameterNames.Add(paramName);
}
}
// For each parameter, use the last query's value and sync to all queries that have it
foreach (var paramName in allParameterNames)
{
object? lastValue = null;
bool parameterFound = false;
// Find the last query that has this parameter and get its value
for (int i = _queryBreakdowns.Count - 1; i >= 0; i--)
{
if (_queryBreakdowns[i].Parameters.ContainsKey(paramName))
{
lastValue = _queryBreakdowns[i].Parameters[paramName];
parameterFound = true;
break;
}
}
// Synchronize the parameter value to all queries that have it
if (parameterFound)
{
foreach (var query in _queryBreakdowns.Where(q => q.Parameters.ContainsKey(paramName)))
{
query.Parameters[paramName] = lastValue!;
}
}
}
}
=> QueryCollectionAnalysisHelper.SynchronizeParameters(_queryBreakdowns);
/// <summary>
/// Adds a parameter to all queries in the collection.
@@ -411,27 +311,8 @@ public class QueryBreakdownCollection : SqlBreakdownCollection
/// Gets all unique parameters from all queries in the collection as a combined dictionary.
/// </summary>
/// <returns>A dictionary containing all unique parameters across all queries.</returns>
protected Dictionary<string, object> GetCombinedParameterDictionary()
{
var combinedParams = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
foreach (var query in _queryBreakdowns)
{
// Add from ParameterList (parsed parameters)
foreach (var param in query.ParameterList)
{
combinedParams[param.Name] = param.Value;
}
// Add/override from Parameters dictionary (manually added parameters)
foreach (var param in query.Parameters)
{
combinedParams[param.Key] = param.Value;
}
}
return combinedParams;
}
protected Dictionary<string, object?> GetCombinedParameterDictionary()
=> QueryCollectionAnalysisHelper.GetCombinedParameters(_queryBreakdowns);
/// <summary>
/// Gets all unique parameters from all queries in the collection.
@@ -482,54 +363,14 @@ public class QueryBreakdownCollection : SqlBreakdownCollection
/// <returns>Parameter usage information.</returns>
public IEnumerable<ParameterUsageReport> GetParameterUsageReport()
{
// Collect all unique parameter names from both ParameterList and Parameters dictionary
var allParamNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var query in _queryBreakdowns)
{
// Add from ParameterList (parsed parameters)
foreach (var param in query.ParameterList)
return QueryCollectionAnalysisHelper.GetParameterUsage(_queryBreakdowns)
.Select(usage => new ParameterUsageReport
{
allParamNames.Add(param.Name);
}
// Add from Parameters dictionary (manually added parameters)
foreach (var paramName in query.Parameters.Keys)
{
allParamNames.Add(paramName);
}
}
foreach (var paramName in allParamNames)
{
var queriesUsing = 0;
object? lastValue = null;
foreach (var query in _queryBreakdowns)
{
// Check ParameterList first (parsed)
var param = query.ParameterList.FirstOrDefault(p => p.Name.Equals(paramName, StringComparison.OrdinalIgnoreCase));
if (param != null)
{
queriesUsing++;
lastValue = param.Value;
}
// Also check Parameters dictionary (manually added)
else if (query.Parameters.TryGetValue(paramName, out var dictValue))
{
queriesUsing++;
lastValue = dictValue;
}
}
yield return new ParameterUsageReport
{
ParameterName = paramName,
Value = lastValue,
UsedInQueryCount = queriesUsing,
TotalQueries = _queryBreakdowns.Count
};
}
ParameterName = usage.Name,
Value = usage.Value,
UsedInQueryCount = usage.UsedInQueryCount,
TotalQueries = usage.TotalQueries
});
}
/// <summary>