using Strata.SqlTools.Breakdowns.LinqToSql; namespace Strata.SqlTools.Builders.LinqToSql; /// /// Fluent builder for constructing LinqQueryBreakdown instances programmatically. /// Useful for scenarios where you don't have a live IQueryable to analyze. /// public class LinqQueryBreakdownBuilder { private readonly List _selectColumns = []; private string? _fromTable; private string? _whereClause; private string? _groupByClause; private string? _havingClause; private string? _orderByClause; /// /// Initializes a new instance of the class. /// public LinqQueryBreakdownBuilder() { } /// /// Sets the SELECT columns for the query. /// /// Column names to select. /// This builder for method chaining. public LinqQueryBreakdownBuilder SelectColumns(params string[] columns) { if (columns.Length == 0) { _selectColumns.Add("*"); } else { _selectColumns.AddRange(columns); } return this; } /// /// Sets the SELECT to all columns (*). /// /// This builder for method chaining. public LinqQueryBreakdownBuilder SelectAll() { _selectColumns.Clear(); _selectColumns.Add("*"); return this; } /// /// Sets the FROM table for the query. /// /// The table name. /// This builder for method chaining. public LinqQueryBreakdownBuilder FromTable(string tableName) { if (string.IsNullOrWhiteSpace(tableName)) { throw new ArgumentException("Table name cannot be null or empty.", nameof(tableName)); } _fromTable = tableName; return this; } /// /// Sets the WHERE clause for the query. /// /// The WHERE condition. /// This builder for method chaining. public LinqQueryBreakdownBuilder Where(string condition) { if (!string.IsNullOrWhiteSpace(condition)) { _whereClause = condition; } return this; } /// /// Sets the GROUP BY clause for the query. /// /// The columns to group by. /// This builder for method chaining. public LinqQueryBreakdownBuilder GroupBy(params string[] columns) { if (columns.Length > 0) { _groupByClause = string.Join(", ", columns); } return this; } /// /// Sets the HAVING clause for the query. /// /// The HAVING condition. /// This builder for method chaining. public LinqQueryBreakdownBuilder Having(string condition) { if (!string.IsNullOrWhiteSpace(condition)) { _havingClause = condition; } return this; } /// /// Sets the ORDER BY clause for the query. /// /// The ORDER BY specification (e.g., "Name ASC, Age DESC"). /// This builder for method chaining. public LinqQueryBreakdownBuilder OrderBy(string orderSpecification) { if (!string.IsNullOrWhiteSpace(orderSpecification)) { _orderByClause = orderSpecification; } return this; } /// /// Adds an ORDER BY clause in ascending order. /// /// The column to order by. /// This builder for method chaining. public LinqQueryBreakdownBuilder OrderByAscending(string column) { if (string.IsNullOrWhiteSpace(column)) { throw new ArgumentException("Column name cannot be null or empty.", nameof(column)); } _orderByClause = $"{column} ASC"; return this; } /// /// Adds an ORDER BY clause in descending order. /// /// The column to order by. /// This builder for method chaining. public LinqQueryBreakdownBuilder OrderByDescending(string column) { if (string.IsNullOrWhiteSpace(column)) { throw new ArgumentException("Column name cannot be null or empty.", nameof(column)); } _orderByClause = $"{column} DESC"; return this; } /// /// Builds and returns the LinqQueryBreakdown instance. /// /// A new LinqQueryBreakdown with the configured clauses. /// Thrown when required clauses are missing. public LinqQueryBreakdown Build() { if (_selectColumns.Count == 0) { throw new InvalidOperationException("At least one SELECT column must be specified."); } if (string.IsNullOrWhiteSpace(_fromTable)) { throw new InvalidOperationException("FROM table must be specified."); } var breakdown = new LinqQueryBreakdown( string.Join(", ", _selectColumns), _fromTable, _whereClause ?? string.Empty ); if (!string.IsNullOrWhiteSpace(_groupByClause)) { breakdown.GroupByClause.Clause = _groupByClause; } if (!string.IsNullOrWhiteSpace(_havingClause)) { breakdown.HavingClause.Clause = _havingClause; } if (!string.IsNullOrWhiteSpace(_orderByClause)) { breakdown.OrderByClause.Clause = _orderByClause; } return breakdown; } /// /// Gets a SQL Server formatted preview of the query being built. /// /// Preview SQL statement. public string PreviewSql() { try { return Build().ToSqlServerSql(); } catch (InvalidOperationException) { return "-- Incomplete query (missing required clauses)"; } } /// /// Creates a new builder with the default state. /// /// A new LinqQueryBreakdownBuilder instance. public static LinqQueryBreakdownBuilder Create() { return new LinqQueryBreakdownBuilder(); } /// /// Creates a builder with a table already specified. /// /// The table to select from. /// A new builder with the table set. public static LinqQueryBreakdownBuilder CreateForTable(string tableName) { return new LinqQueryBreakdownBuilder().FromTable(tableName); } }