refactor(dedup): share TryParse prelude across breakdown families (Cluster D)
The standard `TryParse(...)` prelude — null/empty check, parser construction, comment-preserving normalize, statement-prefix regex validation, setup/finish clause extraction — was copy-pasted in **eight** breakdown classes across the SqlServer and Snowflake dialects. Sonar flagged it as a six-way duplicate cluster on the shorter (~17-line) common block, and as additional pairwise duplicates on the longer (~30-line) version. Introduces `Strata.SqlTools.Statements.SqlServer.ParsePreparation` with a single `TryRunPrelude(sql, parser, prefixRegex, prefixDescription, out ...)` method. Each `TryParse` now calls it once and proceeds straight to dialect-specific match logic. Touched callers: - `SqlServer.InsertBreakdown`, `SqlServer.DeleteBreakdown`, `SqlServer.UpdateBreakdown`, `SqlServer.ProcedureBreakdown` - `Snowflake.InsertBreakdown`, `Snowflake.DeleteBreakdown`, `Snowflake.UpdateBreakdown`, `Snowflake.ProcedureBreakdown` The Microsoft-SQL fallback path in the Snowflake breakdowns (which delegates to the SqlServer breakdown's TryParse before the prelude even runs) is preserved unchanged. `ParsePreparation` is `public` because it sits in the SqlServer assembly and is consumed cross-assembly by Snowflake/PostgreSql. This is a new public type but it's deliberately a thin scaffold — external consumers should still be calling the breakdown classes' own `TryParse` methods. All 1180 tests stay green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
4b5348c53a
commit
c121dfa611
@@ -146,31 +146,14 @@ public class DeleteBreakdown : SqlBreakdownBase
|
||||
result = null!;
|
||||
errorMessage = null!;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(sql))
|
||||
{
|
||||
errorMessage = "SQL statement cannot be null or empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
var parser = new StatementParser();
|
||||
sql = parser.NormalizeSqlPreservingComments(sql);
|
||||
|
||||
// Check if it's a DELETE statement
|
||||
var sqlTrimmed = sql.TrimStart();
|
||||
if (!System.Text.RegularExpressions.Regex.IsMatch(sqlTrimmed, @"^\s*DELETE\b",
|
||||
System.Text.RegularExpressions.RegexOptions.IgnoreCase, Strata.SqlTools.SqlBreakdown.Utilities.RegexDefaults.MatchTimeout))
|
||||
if (!Strata.SqlTools.Statements.SqlServer.ParsePreparation.TryRunPrelude(
|
||||
sql, parser, @"^\s*DELETE\b", "DELETE",
|
||||
out sql, out var setupClauses, out var finishClauses, out errorMessage))
|
||||
{
|
||||
errorMessage = "SQL statement must start with DELETE.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extract setup and finish clauses
|
||||
var setupClauses = new List<string>();
|
||||
sql = parser.ExtractSetupClauses(sql, setupClauses);
|
||||
|
||||
var finishClauses = new ArrayList();
|
||||
sql = parser.ExtractFinishClauses(sql, finishClauses);
|
||||
|
||||
// Parse DELETE statement using regex
|
||||
// Pattern: DELETE [table_alias] FROM table WHERE condition
|
||||
var deleteMatch = System.Text.RegularExpressions.Regex.Match(sql,
|
||||
|
||||
Reference in New Issue
Block a user