From 507620cc0469b47acddba101b5f79061af324212 Mon Sep 17 00:00:00 2001 From: Thom Lamb Date: Wed, 27 May 2026 17:05:00 -0500 Subject: [PATCH] refactor(dedup): redundant Snowflake override + shared Insert regex helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two follow-ups to the prior dedup pass: - **Delete `Snowflake.UpdateBreakdown.GetSqlBreakdown`**: it was a byte-for-byte copy of the SqlServer base's `GetSqlBreakdown` (modulo one explanatory comment). Snowflake's UPDATE syntax — including the FROM clause — is identical at the formatter level, so the override was pure inheritance noise. Now inherits. - **Extract `ParsePreparation.TryMatchInsertSql`**: the regex match + group extraction + failure message at the end of `SqlServer.InsertBreakdown.TryParse` and `Snowflake.InsertBreakdown.TryParse` was duplicated. Hoist the shared piece next to `TryRunPrelude` on `ParsePreparation`. Both callers continue to construct their own `InsertBreakdown` instance (the constructor signatures differ slightly between dialects). All 1180 tests stay green. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Breakdowns/InsertBreakdown.cs | 13 ++------ .../Breakdowns/UpdateBreakdown.cs | 31 ++--------------- .../Breakdowns/InsertBreakdown.cs | 14 ++------ .../Statements/ParsePreparation.cs | 33 +++++++++++++++++++ 4 files changed, 39 insertions(+), 52 deletions(-) diff --git a/src/Strata.SqlTools.Snowflake/Breakdowns/InsertBreakdown.cs b/src/Strata.SqlTools.Snowflake/Breakdowns/InsertBreakdown.cs index 89f3d06..777c677 100644 --- a/src/Strata.SqlTools.Snowflake/Breakdowns/InsertBreakdown.cs +++ b/src/Strata.SqlTools.Snowflake/Breakdowns/InsertBreakdown.cs @@ -143,21 +143,12 @@ public class InsertBreakdown : SqlServerInsertBreakdown return false; } - // Parse INSERT statement using regex - var insertMatch = System.Text.RegularExpressions.Regex.Match(sql, - @"INSERT\s+INTO\s+([^\(\s]+)\s*\(([^\)]*)\)\s*VALUES\s*\(([^\)]*)\)", - System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline, Strata.SqlTools.SqlBreakdown.Utilities.RegexDefaults.MatchTimeout); - - if (!insertMatch.Success) + if (!Strata.SqlTools.Statements.SqlServer.ParsePreparation.TryMatchInsertSql( + sql, out var tableName, out var columnsClause, out var valuesClause, out errorMessage)) { - errorMessage = "Could not parse INSERT statement. Expected format: INSERT INTO table (columns) VALUES (values)"; return false; } - var tableName = insertMatch.Groups[1].Value.Trim(); - var columnsClause = insertMatch.Groups[2].Value.Trim(); - var valuesClause = insertMatch.Groups[3].Value.Trim(); - result = new InsertBreakdown(tableName, columnsClause, valuesClause, isMicrosoftSql: false) { SetupClauses = setupClauses, diff --git a/src/Strata.SqlTools.Snowflake/Breakdowns/UpdateBreakdown.cs b/src/Strata.SqlTools.Snowflake/Breakdowns/UpdateBreakdown.cs index 5895dc1..056fc64 100644 --- a/src/Strata.SqlTools.Snowflake/Breakdowns/UpdateBreakdown.cs +++ b/src/Strata.SqlTools.Snowflake/Breakdowns/UpdateBreakdown.cs @@ -44,35 +44,8 @@ public class UpdateBreakdown : SqlServerUpdateBreakdown WhereClause.Comment = whereComments.Count > 0 ? string.Join(" ", whereComments) : null; } - /// - /// Gets the SQL breakdown as a string for Snowflake. - /// - /// The UPDATE SQL statement. - protected override string GetSqlBreakdown() - { - var sb = new StringBuilder(); - - sb.AppendLine("UPDATE "); - sb.AppendLine($" {TableName.Clause}"); - - sb.AppendLine("SET "); - sb.AppendLine($" {SetClause.Clause}"); - - if (IsUsingFromClause) - { - // Snowflake supports FROM clause in UPDATE - sb.AppendLine("FROM "); - sb.AppendLine($" {FromClause.Clause}"); - } - - if (IsUsingWhereClause) - { - sb.AppendLine("WHERE "); - sb.AppendLine($" {WhereClause.Clause}"); - } - - return sb.ToString(); - } + // GetSqlBreakdown() inherited from SqlServer.UpdateBreakdown — Snowflake's UPDATE syntax + // (including the optional FROM clause) is identical at the formatter level, so no override needed. #region Parse Methods diff --git a/src/Strata.SqlTools.SqlServer/Breakdowns/InsertBreakdown.cs b/src/Strata.SqlTools.SqlServer/Breakdowns/InsertBreakdown.cs index dd77b77..20198b9 100644 --- a/src/Strata.SqlTools.SqlServer/Breakdowns/InsertBreakdown.cs +++ b/src/Strata.SqlTools.SqlServer/Breakdowns/InsertBreakdown.cs @@ -152,22 +152,12 @@ public class InsertBreakdown : SqlBreakdownBase return false; } - // Parse INSERT statement using regex - // Pattern: INSERT INTO table (columns) VALUES (values) - var insertMatch = System.Text.RegularExpressions.Regex.Match(sql, - @"INSERT\s+INTO\s+([^\(\s]+)\s*\(([^\)]*)\)\s*VALUES\s*\(([^\)]*)\)", - System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline, Strata.SqlTools.SqlBreakdown.Utilities.RegexDefaults.MatchTimeout); - - if (!insertMatch.Success) + if (!Strata.SqlTools.Statements.SqlServer.ParsePreparation.TryMatchInsertSql( + sql, out var tableName, out var columnsClause, out var valuesClause, out errorMessage)) { - errorMessage = "Could not parse INSERT statement. Expected format: INSERT INTO table (columns) VALUES (values)"; return false; } - var tableName = insertMatch.Groups[1].Value.Trim(); - var columnsClause = insertMatch.Groups[2].Value.Trim(); - var valuesClause = insertMatch.Groups[3].Value.Trim(); - result = new InsertBreakdown(tableName, columnsClause, valuesClause) { SetupClauses = setupClauses, diff --git a/src/Strata.SqlTools.SqlServer/Statements/ParsePreparation.cs b/src/Strata.SqlTools.SqlServer/Statements/ParsePreparation.cs index 489a0e7..e3eadce 100644 --- a/src/Strata.SqlTools.SqlServer/Statements/ParsePreparation.cs +++ b/src/Strata.SqlTools.SqlServer/Statements/ParsePreparation.cs @@ -66,4 +66,37 @@ public static class ParsePreparation return true; } + + /// + /// Runs the shared INSERT-statement match used by SqlServer / Snowflake (and any future + /// dialect that accepts the same INSERT INTO table (cols) VALUES (vals) grammar). + /// + /// The SQL passed through . + /// On success, the matched table name (trimmed). + /// On success, the matched column list (trimmed). + /// On success, the matched values list (trimmed). + /// On failure, a human-readable parse-error message. + /// true if the regex matched and the three groups are populated; false otherwise. + public static bool TryMatchInsertSql(string sql, out string tableName, out string columnsClause, out string valuesClause, out string errorMessage) + { + tableName = null!; + columnsClause = null!; + valuesClause = null!; + errorMessage = null!; + + var insertMatch = Regex.Match(sql, + @"INSERT\s+INTO\s+([^\(\s]+)\s*\(([^\)]*)\)\s*VALUES\s*\(([^\)]*)\)", + RegexOptions.IgnoreCase | RegexOptions.Singleline, RegexDefaults.MatchTimeout); + + if (!insertMatch.Success) + { + errorMessage = "Could not parse INSERT statement. Expected format: INSERT INTO table (columns) VALUES (values)"; + return false; + } + + tableName = insertMatch.Groups[1].Value.Trim(); + columnsClause = insertMatch.Groups[2].Value.Trim(); + valuesClause = insertMatch.Groups[3].Value.Trim(); + return true; + } }