fix: resolving more duplicate lines issue
SonarQube Analysis / sonarqube (pull_request) Successful in 3m55s

This commit is contained in:
Thom Lamb
2026-05-21 14:53:21 -05:00
parent c8b989c11f
commit 2e483c9fa8
4 changed files with 253 additions and 394 deletions
@@ -1,6 +1,4 @@
using System.Text;
using Strata.SqlTools.SqlBreakdown.Classes;
using Strata.SqlTools.SqlBreakdown.Interfaces;
namespace Strata.SqlTools.Breakdowns.SqlServer;
@@ -11,88 +9,21 @@ 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 : SqlBreakdownCollection
public class QueryBreakdownCollection : QueryBreakdownCollectionBase<QueryBreakdown>
{
private readonly List<QueryBreakdown> _queryBreakdowns;
/// <summary>
/// Initializes a new instance of the <see cref="QueryBreakdownCollection"/> class.
/// </summary>
public QueryBreakdownCollection() : base()
{
_queryBreakdowns = new List<QueryBreakdown>();
}
/// <summary>
/// Initializes a new instance of the <see cref="QueryBreakdownCollection"/> class with initial query breakdowns.
/// </summary>
/// <param name="queryBreakdowns">The initial collection of query breakdowns.</param>
public QueryBreakdownCollection(IEnumerable<QueryBreakdown> queryBreakdowns) : base(queryBreakdowns?.Cast<ISqlBreakdown>() ?? Enumerable.Empty<ISqlBreakdown>())
public QueryBreakdownCollection(IEnumerable<QueryBreakdown> queryBreakdowns) : base(queryBreakdowns)
{
_queryBreakdowns = new List<QueryBreakdown>(queryBreakdowns ?? Enumerable.Empty<QueryBreakdown>());
}
/// <summary>
/// Gets the collection of QueryBreakdown objects.
/// </summary>
public IReadOnlyList<QueryBreakdown> QueryBreakdowns => _queryBreakdowns.AsReadOnly();
/// <summary>
/// Adds a QueryBreakdown to the collection.
/// </summary>
/// <param name="queryBreakdown">The query breakdown to add.</param>
/// <exception cref="ArgumentNullException">Thrown when queryBreakdown is null.</exception>
public void Add(QueryBreakdown queryBreakdown)
{
if (queryBreakdown == null)
{
throw new ArgumentNullException(nameof(queryBreakdown));
}
_queryBreakdowns.Add(queryBreakdown);
base.Add(queryBreakdown);
}
/// <summary>
/// Adds multiple QueryBreakdowns to the collection.
/// </summary>
/// <param name="queryBreakdowns">The query breakdowns to add.</param>
/// <exception cref="ArgumentNullException">Thrown when queryBreakdowns is null.</exception>
public void AddRange(IEnumerable<QueryBreakdown> queryBreakdowns)
{
if (queryBreakdowns == null)
{
throw new ArgumentNullException(nameof(queryBreakdowns));
}
foreach (var breakdown in queryBreakdowns)
{
Add(breakdown);
}
}
/// <summary>
/// Removes a QueryBreakdown from the collection.
/// </summary>
/// <param name="queryBreakdown">The query breakdown to remove.</param>
/// <returns>True if removed; otherwise, false.</returns>
public bool Remove(QueryBreakdown queryBreakdown)
{
var removed = _queryBreakdowns.Remove(queryBreakdown);
if (removed)
{
base.Remove(queryBreakdown);
}
return removed;
}
/// <summary>
/// Clears all query breakdowns from the collection.
/// </summary>
public new void Clear()
{
_queryBreakdowns.Clear();
base.Clear();
}
/// <summary>
@@ -116,15 +47,15 @@ public class QueryBreakdownCollection : SqlBreakdownCollection
}
// Add all queries with GO separators
if (_queryBreakdowns.Count > 0)
if (QueryBreakdownList.Count > 0)
{
for (int i = 0; i < _queryBreakdowns.Count; i++)
for (int i = 0; i < QueryBreakdownList.Count; i++)
{
var query = _queryBreakdowns[i];
var query = QueryBreakdownList[i];
sb.Append(query.GetSql(includeSetupFinish));
// Add GO separator between queries (not after last)
if (i < _queryBreakdowns.Count - 1)
if (i < QueryBreakdownList.Count - 1)
{
sb.AppendLine();
sb.AppendLine("GO");
@@ -143,88 +74,13 @@ public class QueryBreakdownCollection : SqlBreakdownCollection
return sb.ToString();
}
/// <summary>
/// Filters query breakdowns where the SELECT clause contains specific text.
/// </summary>
/// <param name="selectContains">The text to find in the SELECT clause.</param>
/// <returns>Filtered query breakdowns.</returns>
public IEnumerable<QueryBreakdown> WhereSelectContains(string selectContains)
{
if (string.IsNullOrWhiteSpace(selectContains))
{
throw new ArgumentNullException(nameof(selectContains));
}
return _queryBreakdowns.Where(q =>
q.SelectClause?.Clause?.Contains(selectContains, StringComparison.OrdinalIgnoreCase) ?? false);
}
/// <summary>
/// Filters query breakdowns where the FROM clause contains specific text.
/// </summary>
/// <param name="tableNameContains">The table name or pattern to find.</param>
/// <returns>Filtered query breakdowns.</returns>
public IEnumerable<QueryBreakdown> WhereTableContains(string tableNameContains)
{
if (string.IsNullOrWhiteSpace(tableNameContains))
{
throw new ArgumentNullException(nameof(tableNameContains));
}
return _queryBreakdowns.Where(q =>
q.FromClause?.Clause?.Contains(tableNameContains, StringComparison.OrdinalIgnoreCase) ?? false);
}
/// <summary>
/// Filters query breakdowns that have a WHERE clause.
/// </summary>
/// <returns>Query breakdowns with WHERE clauses.</returns>
public IEnumerable<QueryBreakdown> WhereHaveWhereClause()
{
return _queryBreakdowns.Where(q =>
!string.IsNullOrWhiteSpace(q.WhereClause?.Clause));
}
/// <summary>
/// Filters query breakdowns that do NOT have a WHERE clause.
/// </summary>
/// <remarks>
/// This is useful for identifying potentially risky queries that affect all rows.
/// </remarks>
/// <returns>Query breakdowns without WHERE clauses.</returns>
public IEnumerable<QueryBreakdown> WhereHaveNoWhereClause()
{
return _queryBreakdowns.Where(q =>
string.IsNullOrWhiteSpace(q.WhereClause?.Clause));
}
/// <summary>
/// Filters query breakdowns that have a GROUP BY clause.
/// </summary>
/// <returns>Query breakdowns with GROUP BY clauses.</returns>
public IEnumerable<QueryBreakdown> WhereHaveGroupByClause()
{
return _queryBreakdowns.Where(q =>
!string.IsNullOrWhiteSpace(q.GroupByClause?.Clause));
}
/// <summary>
/// Filters query breakdowns that have an ORDER BY clause.
/// </summary>
/// <returns>Query breakdowns with ORDER BY clauses.</returns>
public IEnumerable<QueryBreakdown> WhereHaveOrderByClause()
{
return _queryBreakdowns.Where(q =>
!string.IsNullOrWhiteSpace(q.OrderByClause?.Clause));
}
/// <summary>
/// Filters query breakdowns that have WITH clauses (CTEs).
/// </summary>
/// <returns>Query breakdowns with CTE definitions.</returns>
public IEnumerable<QueryBreakdown> WhereHaveCommonTableExpressions()
{
return _queryBreakdowns.Where(q => q.WithClauses.Count > 0);
return QueryBreakdownList.Where(q => q.WithClauses.Count > 0);
}
/// <summary>
@@ -233,7 +89,7 @@ public class QueryBreakdownCollection : SqlBreakdownCollection
/// <returns>Query breakdowns with JOINs.</returns>
public IEnumerable<QueryBreakdown> WhereHaveJoins()
{
return _queryBreakdowns.Where(q => q.GetSql().Contains("JOIN", StringComparison.OrdinalIgnoreCase));
return QueryBreakdownList.Where(q => q.GetSql().Contains("JOIN", StringComparison.OrdinalIgnoreCase));
}
/// <summary>
@@ -248,47 +104,10 @@ public class QueryBreakdownCollection : SqlBreakdownCollection
throw new ArgumentNullException(nameof(parameterName));
}
return _queryBreakdowns.Where(q =>
return QueryBreakdownList.Where(q =>
q.ParameterList.Any(p => p.Name == parameterName));
}
/// <summary>
/// Gets the total number of columns selected across all queries.
/// </summary>
/// <returns>Total column count.</returns>
public int GetTotalSelectedColumns()
=> QueryCollectionAnalysisHelper.GetTotalSelectedColumns(_queryBreakdowns);
/// <summary>
/// Gets all unique table names referenced across all queries.
/// </summary>
/// <remarks>
/// This provides a quick overview of which tables are being queried.
/// Note: This is a best-effort extraction and may not capture all table references,
/// especially in complex subqueries or with aliasing.
/// </remarks>
/// <returns>List of unique table names.</returns>
public IEnumerable<string> GetUniqueTableReferences()
=> 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()
=> QueryCollectionAnalysisHelper.GetQuerySummaries(_queryBreakdowns);
/// <summary>
/// Synchronizes parameters across all queries in the collection.
/// </summary>
/// <remarks>
/// This ensures all queries share the same parameter values based on parameter name.
/// Later parameter values override earlier ones if there are conflicts.
/// Only synchronizes parameters that the query already defines to avoid adding unused parameters.
/// </remarks>
public void SynchronizeParameters()
=> QueryCollectionAnalysisHelper.SynchronizeParameters(_queryBreakdowns);
/// <summary>
/// Adds a parameter to all queries in the collection.
/// </summary>
@@ -301,23 +120,18 @@ public class QueryBreakdownCollection : SqlBreakdownCollection
throw new ArgumentNullException(nameof(parameterName));
}
foreach (var query in _queryBreakdowns)
foreach (var query in QueryBreakdownList)
{
query.Parameters[parameterName] = value!;
}
}
/// <summary>
/// Gets all unique parameters from all queries in the collection as a combined dictionary.
/// Gets a summary of all queries including their types and basic composition.
/// </summary>
/// <returns>A dictionary containing all unique parameters across all queries.</returns>
protected Dictionary<string, object?> GetCombinedParameterDictionary()
=> QueryCollectionAnalysisHelper.GetCombinedParameters(_queryBreakdowns);
/// <summary>
/// Gets all unique parameters from all queries in the collection.
/// </summary>
/// <returns>A collection of unique QueryParam objects.</returns>
/// <returns>Summary information for each query.</returns>
public IEnumerable<QuerySummary> GetQuerySummaries()
=> QueryCollectionAnalysisHelper.GetQuerySummaries(QueryBreakdownList);
/// <summary>
/// Gets all T-SQL parameters as a formatted string suitable for SQL Server.
@@ -363,7 +177,7 @@ public class QueryBreakdownCollection : SqlBreakdownCollection
/// <returns>Parameter usage information.</returns>
public IEnumerable<ParameterUsageReport> GetParameterUsageReport()
{
return QueryCollectionAnalysisHelper.GetParameterUsage(_queryBreakdowns)
return QueryCollectionAnalysisHelper.GetParameterUsage(QueryBreakdownList)
.Select(usage => new ParameterUsageReport
{
ParameterName = usage.Name,