refactor(dedup): extract AppendWithClauseSection for the WITH/CTE block

`SqlServer.QueryBreakdown.GetSqlBreakdown` and
`Snowflake.QueryBreakdown.GetSql` each carried a 24-line copy of the
same CTE-rendering loop ("WITH" keyword, optional RECURSIVE, per-clause
header, anchor/UNION ALL/recursive query, closing parens). The two
copies differed only by indent (5/10 spaces vs 4/8) and a trailing
space after the keyword.

Hoist the loop into `protected virtual void AppendWithClauseSection(
StringBuilder, string withClauseIndent, string queryBodyIndent)` on
`SqlServer.QueryBreakdown`. Each caller invokes it with its dialect's
preferred indents; Snowflake's mid-method copy is deleted entirely.

Standardizes on the no-trailing-space "WITH" form (Snowflake's) — was
"WITH " (trailing space) in the SqlServer original. Visible only as a
trailing space before the newline in non-recursive output, which no
tests assert on.

All 1180 tests stay green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Thom Lamb
2026-05-27 17:23:48 -05:00
co-authored by Claude Opus 4.7
parent 620b85a61d
commit 089d4f6000
2 changed files with 66 additions and 116 deletions
@@ -451,62 +451,7 @@ public class QueryBreakdown : SqlServerQueryBreakdown
}
}
if (IsUsingWithClause)
{
// Check if any WITH clause is recursive
bool hasRecursive = WithClauses.Any(wc => wc.IsRecursive);
sb.Append("WITH");
if (hasRecursive)
{
sb.Append(" RECURSIVE");
}
sb.AppendLine();
for (int i = 0; i < WithClauses.Count; i++)
{
var withClause = WithClauses[i];
if (i > 0)
{
sb.Append(',');
sb.AppendLine();
}
// Include comment if present
if (!string.IsNullOrWhiteSpace(withClause.Comment))
{
sb.AppendLine($" {withClause.Comment}");
}
// Write CTE name with optional column list
var cteName = withClause.TableName;
if (withClause.ColumnList != null && withClause.ColumnList.Count > 0)
{
var columnList = string.Join(", ", withClause.ColumnList);
cteName = $"{withClause.TableName} ({columnList})";
}
sb.AppendLine($" {cteName} AS (");
if (withClause.IsRecursive && withClause.RecursiveQuery != null)
{
// For recursive CTEs: anchor query UNION ALL recursive query
var anchorSql = withClause.Query?.GetSql(includeSetupFinish: false).Trim() ?? string.Empty;
var recursiveSql = withClause.RecursiveQuery.GetSql(includeSetupFinish: false).Trim() ?? string.Empty;
sb.AppendLine($" {anchorSql}");
sb.AppendLine(" UNION ALL");
sb.AppendLine($" {recursiveSql}");
}
else
{
// For non-recursive CTEs: just the single query
var withSql = withClause.Query?.GetSql(includeSetupFinish: false).Trim() ?? string.Empty;
sb.AppendLine($" {withSql}");
}
sb.Append(" )");
}
sb.AppendLine();
}
AppendWithClauseSection(sb, withClauseIndent: " ", queryBodyIndent: " ");
// Snowflake SELECT syntax
sb.Append(StatementParser.KeywordSelect);