using Strata.SqlTools.SqlBreakdown.Classes;
using Strata.SqlTools.SqlBreakdown.Interfaces;
namespace Strata.SqlTools.Breakdowns.SqlServer;
///
/// Base collection that manages a strongly typed list of query breakdowns and provides the
/// dialect-agnostic plumbing, filters, and analysis shared by the per-dialect collections.
///
/// The concrete query breakdown type held by the collection.
///
/// Each dialect collection closes the generic over its own query type (for example,
/// QueryBreakdownCollectionBase<Snowflake.QueryBreakdown>) so that public members such as
/// and the Where* filters keep their dialect-specific element type.
///
public abstract class QueryBreakdownCollectionBase : SqlBreakdownCollection
where TQuery : QueryBreakdown
{
///
/// Gets the backing list of typed query breakdowns.
///
protected List QueryBreakdownList { get; }
///
/// Initializes a new, empty instance.
///
protected QueryBreakdownCollectionBase() : base()
{
QueryBreakdownList = new List();
}
///
/// Initializes a new instance with initial query breakdowns.
///
/// The initial collection of query breakdowns.
protected QueryBreakdownCollectionBase(IEnumerable queryBreakdowns)
: base(queryBreakdowns?.Cast() ?? Enumerable.Empty())
{
QueryBreakdownList = new List(queryBreakdowns ?? Enumerable.Empty());
}
///
/// Gets the collection of query breakdowns.
///
public IReadOnlyList QueryBreakdowns => QueryBreakdownList.AsReadOnly();
///
/// Adds a query breakdown to the collection.
///
/// The query breakdown to add.
/// Thrown when is null.
public void Add(TQuery queryBreakdown)
{
ArgumentNullException.ThrowIfNull(queryBreakdown);
QueryBreakdownList.Add(queryBreakdown);
base.Add(queryBreakdown);
}
///
/// Adds multiple query breakdowns to the collection.
///
/// The query breakdowns to add.
/// Thrown when is null.
public void AddRange(IEnumerable queryBreakdowns)
{
ArgumentNullException.ThrowIfNull(queryBreakdowns);
foreach (var breakdown in queryBreakdowns)
{
Add(breakdown);
}
}
///
/// Removes a query breakdown from the collection.
///
/// The query breakdown to remove.
/// True if removed; otherwise, false.
public bool Remove(TQuery queryBreakdown)
{
var removed = QueryBreakdownList.Remove(queryBreakdown);
if (removed)
{
base.Remove(queryBreakdown);
}
return removed;
}
///
/// Clears all query breakdowns from the collection.
///
public new void Clear()
{
QueryBreakdownList.Clear();
base.Clear();
}
///
/// Filters query breakdowns where the SELECT clause contains specific text.
///
/// The text to find in the SELECT clause.
/// Filtered query breakdowns.
public IEnumerable WhereSelectContains(string selectContains)
{
if (string.IsNullOrWhiteSpace(selectContains))
{
throw new ArgumentNullException(nameof(selectContains));
}
return QueryBreakdownList.Where(q =>
q.SelectClause?.Clause?.Contains(selectContains, StringComparison.OrdinalIgnoreCase) ?? false);
}
///
/// Filters query breakdowns where the FROM clause contains specific text.
///
/// The table name or pattern to find.
/// Filtered query breakdowns.
public IEnumerable WhereTableContains(string tableNameContains)
{
if (string.IsNullOrWhiteSpace(tableNameContains))
{
throw new ArgumentNullException(nameof(tableNameContains));
}
return QueryBreakdownList.Where(q =>
q.FromClause?.Clause?.Contains(tableNameContains, StringComparison.OrdinalIgnoreCase) ?? false);
}
///
/// Filters query breakdowns that have a WHERE clause.
///
/// Query breakdowns with WHERE clauses.
public IEnumerable WhereHaveWhereClause()
{
return QueryBreakdownList.Where(q =>
!string.IsNullOrWhiteSpace(q.WhereClause?.Clause));
}
///
/// Filters query breakdowns that do NOT have a WHERE clause.
///
///
/// This is useful for identifying potentially risky queries that affect all rows.
///
/// Query breakdowns without WHERE clauses.
public IEnumerable WhereHaveNoWhereClause()
{
return QueryBreakdownList.Where(q =>
string.IsNullOrWhiteSpace(q.WhereClause?.Clause));
}
///
/// Filters query breakdowns that have a GROUP BY clause.
///
/// Query breakdowns with GROUP BY clauses.
public IEnumerable WhereHaveGroupByClause()
{
return QueryBreakdownList.Where(q =>
!string.IsNullOrWhiteSpace(q.GroupByClause?.Clause));
}
///
/// Filters query breakdowns that have an ORDER BY clause.
///
/// Query breakdowns with ORDER BY clauses.
public IEnumerable WhereHaveOrderByClause()
{
return QueryBreakdownList.Where(q =>
!string.IsNullOrWhiteSpace(q.OrderByClause?.Clause));
}
///
/// Gets the total number of columns selected across all queries.
///
/// Total column count.
public int GetTotalSelectedColumns()
=> QueryCollectionAnalysisHelper.GetTotalSelectedColumns(QueryBreakdownList);
///
/// Gets all unique table names referenced across all queries.
///
///
/// 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.
///
/// List of unique table names.
public IEnumerable GetUniqueTableReferences()
=> QueryCollectionAnalysisHelper.GetUniqueTableReferences(QueryBreakdownList);
///
/// Synchronizes parameter values across all queries in the collection.
///
///
/// Ensures all queries share the same parameter value based on parameter name. Later parameter
/// values override earlier ones if there are conflicts. Only parameters a query already defines
/// are synchronized, to avoid adding unused parameters.
///
public void SynchronizeParameters()
=> QueryCollectionAnalysisHelper.SynchronizeParameters(QueryBreakdownList);
///
/// Gets all unique parameters from all queries in the collection as a combined dictionary.
///
/// A dictionary containing all unique parameters across all queries.
protected Dictionary GetCombinedParameterDictionary()
=> QueryCollectionAnalysisHelper.GetCombinedParameters(QueryBreakdownList);
}