refactor(dedup): cross-dialect QueryBreakdown + StatementParser helpers (Cluster E)
SonarQube Analysis / sonarqube (pull_request) Successful in 4m5s

Two shared scaffolds for blocks Sonar flagged across the SqlServer,
Snowflake, and PostgreSQL dialects:

1. **`AppendToClause` on `SqlBreakdownBase`** — collapses the "if
   clause is empty set it, else append `{operation} {sql}`; then merge
   comment with same rule" pattern that was repeated three times in
   each of SqlServer/Snowflake `QueryBreakdown`. The matching
   `AddWhereExpression` / `AddHavingExpression` / `AddWhereClause(string)`
   sites in both files now delegate to a single `protected static`
   helper. Operates against `ISqlClause`, so it works for both the
   `WhereClause` and `HavingClause` properties.

2. **`HandleDoubleQuoteAsIdentifier` on `SqlServer.StatementParser`** —
   PostgreSQL and Snowflake both override SqlServer's
   `HandleDoubleQuote` (which produces a string-literal token) to
   instead produce a `ColumnIdentifier` token. The two overrides had
   identical 14-line bodies. The shared logic now lives once, and
   each dialect's override is a one-liner that calls the helper.

Deliberately *not* refactored in this commit:
- The CTE WITH-clause SQL generation in SqlServer/Snowflake QueryBreakdown
  (lines ~537-560 / ~579-601 Sonar flagged) — the surrounding logic
  differs enough between the two that an extraction would obscure
  rather than clarify.
- The PG/Snowflake QueryBreakdown constructor pair (lines 40-58 /
  43-61) — only ~10 lines × 2; extracting requires either a new
  shared helper for ~20 lines of savings or moving up the inheritance
  chain, neither pays for itself.

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 16:39:36 -05:00
co-authored by Claude Opus 4.7
parent c121dfa611
commit f577c06558
6 changed files with 72 additions and 166 deletions
@@ -822,29 +822,9 @@ public class QueryBreakdown : SqlBreakdownBase, IQueryBreakdown
// Extract comments from the incoming SQL
var cleanSql = Parser.ExtractSqlComments(sql, out var comments);
var commentText = comments.Count > 0 ? string.Join(" ", comments) : null;
if (string.IsNullOrWhiteSpace(WhereClause.Clause))
{
WhereClause.Clause = cleanSql.Trim();
}
else
{
WhereClause.Clause = $"{WhereClause.Clause} {operation} {cleanSql.Trim()}";
}
// Merge comments
if (comments.Count > 0)
{
var newComment = string.Join(" ", comments);
if (string.IsNullOrWhiteSpace(WhereClause.Comment))
{
WhereClause.Comment = newComment;
}
else
{
WhereClause.Comment = $"{WhereClause.Comment} {newComment}";
}
}
AppendToClause(WhereClause, cleanSql.Trim(), operation, commentText);
// Extract and add parameters from the WHERE clause
ExtractAndAddParameters(cleanSql);
@@ -901,28 +881,7 @@ public class QueryBreakdown : SqlBreakdownBase, IQueryBreakdown
}
var visitor = new CommandVisitor();
var sql = expression.Accept(visitor);
if (string.IsNullOrWhiteSpace(WhereClause.Clause))
{
WhereClause.Clause = sql;
}
else
{
WhereClause.Clause = $"{WhereClause.Clause} {operation} {sql}";
}
if (!string.IsNullOrWhiteSpace(comment))
{
if (string.IsNullOrWhiteSpace(WhereClause.Comment))
{
WhereClause.Comment = comment;
}
else
{
WhereClause.Comment = $"{WhereClause.Comment} {comment}";
}
}
AppendToClause(WhereClause, expression.Accept(visitor), operation, comment);
}
/// <summary>
@@ -1013,28 +972,7 @@ public class QueryBreakdown : SqlBreakdownBase, IQueryBreakdown
}
var visitor = new CommandVisitor();
var sql = expression.Accept(visitor);
if (string.IsNullOrWhiteSpace(HavingClause.Clause))
{
HavingClause.Clause = sql;
}
else
{
HavingClause.Clause = $"{HavingClause.Clause} {operation} {sql}";
}
if (!string.IsNullOrWhiteSpace(comment))
{
if (string.IsNullOrWhiteSpace(HavingClause.Comment))
{
HavingClause.Comment = comment;
}
else
{
HavingClause.Comment = $"{HavingClause.Comment} {comment}";
}
}
AppendToClause(HavingClause, expression.Accept(visitor), operation, comment);
}
/// <summary>