Files
sql-utilities/src/Strata.SqlTools.SqlBreakdown/Classes/SqlBreakdownBase.cs
T
Thom LambandClaude Opus 4.7 0f8d505616
SonarQube Analysis / sonarqube (pull_request) Successful in 2m47s
chore(sonar): apply collection-expression syntax across all sites (IDE0028)
Manual sweep of all 42 IDE0028 sites flagged by SonarQube — `dotnet format
analyzers --diagnostics IDE0028` declined to fix these (no .editorconfig
opt-in for `dotnet_style_prefer_collection_expression`), so applied by
hand. The repo already targets `<LangVersion>latest</LangVersion>` on
net8.0, so C# 12 collection expressions are available.

Pattern: `new List<T>()` / `new Dictionary<K,V>()` / `new ArrayList()` /
`new()` -> `[]` for empty; `new List<T> { ... }` -> `[...]` for literal.

24 files touched in src/{EFCore, LinqToSql, Query, Snowflake, SqlBreakdown,
SqlServer}; tests untouched (no IDE0028 sites in test code).

Build clean (35 warnings unchanged from baseline, 0 errors). All tests
remain green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 17:01:30 -05:00

130 lines
4.0 KiB
C#

using System.Collections;
using System.Text;
using Strata.SqlTools.SqlBreakdown.Interfaces;
namespace Strata.SqlTools.SqlBreakdown.Classes;
/// <summary>
/// Base class for SQL query breakdowns that provides common setup/finish clause handling and cloning.
/// </summary>
public abstract class SqlBreakdownBase : ISqlBreakdown
{
/// <summary>
/// Initializes a new instance of the <see cref="SqlBreakdownBase"/> class.
/// </summary>
protected SqlBreakdownBase()
{
SetupClauses = [];
FinishClauses = [];
}
/// <summary>
/// Gets or sets the setup clauses to execute before the main query.
/// </summary>
public List<string> SetupClauses { get; set; }
/// <summary>
/// Gets a value indicating whether setup clauses are being used.
/// </summary>
public bool IsUsingSetupClause => SetupClauses.Count > 0;
/// <summary>
/// Gets or sets the raw/original SQL statement before parsing and breakdown.
/// </summary>
/// <remarks>
/// This property stores the original SQL text that was parsed to create this breakdown.
/// It's useful for auditing, logging, and batch statement retrieval.
/// </remarks>
public string? RawSql { get; set; }
/// <summary>
/// Gets or sets the finish clauses to execute after the main query.
/// </summary>
public ArrayList FinishClauses { get; set; }
/// <summary>
/// Gets a value indicating whether finish clauses are being used.
/// </summary>
public bool IsUsingFinishClause => FinishClauses.Count > 0;
/// <summary>
/// Gets the SQL breakdown as a string. Must be implemented by derived classes.
/// </summary>
/// <returns>The SQL query string.</returns>
protected abstract string GetSqlBreakdown();
/// <summary>
/// Gets a LINQ to SQL query of the specified type based on this breakdown.
/// </summary>
/// <typeparam name="T">The entity type for the query.</typeparam>
/// <returns>An IQueryable of the specified type, or null if the breakdown cannot be converted to a LINQ query.</returns>
/// <remarks>
/// This method allows derived breakdown classes to reconstruct or generate LINQ queries
/// from the analyzed components (SELECT, WHERE, ORDER BY, etc.).
/// The default implementation returns null.
/// </remarks>
public virtual IQueryable<T>? GetQuery<T>() where T : class => null;
/// <summary>
/// Gets the complete SQL query including optional setup and finish clauses.
/// </summary>
/// <param name="includeSetupFinish">Whether to include setup and finish clauses.</param>
/// <returns>The complete SQL query string.</returns>
public string GetSql(bool includeSetupFinish = true)
{
var sb = new StringBuilder();
if (includeSetupFinish)
{
// Write out any setup clauses
sb.AppendLine();
foreach (string setup in SetupClauses)
{
sb.AppendLine(setup);
}
sb.AppendLine();
}
sb.Append(GetSqlBreakdown());
if (includeSetupFinish)
{
// Write out any finish clauses
sb.AppendLine();
sb.AppendLine();
foreach (string finish in FinishClauses)
{
sb.AppendLine(finish);
}
}
return sb.ToString();
}
/// <summary>
/// Returns the SQL query as a string.
/// </summary>
/// <returns>The SQL query string.</returns>
public override string ToString()
=> GetSql();
/// <summary>
/// Creates a deep clone of this object.
/// </summary>
/// <returns>A cloned instance.</returns>
public object Clone()
{
// Create a shallow copy
var clone = (SqlBreakdownBase)MemberwiseClone();
// Deep copy the SetupClauses list
clone.SetupClauses = new List<string>(SetupClauses);
// Deep copy the FinishClauses ArrayList
clone.FinishClauses = new ArrayList(FinishClauses);
return clone;
}
}