using Strata.SqlTools.Breakdowns.Snowflake; namespace Strata.SqlTools.SqlBreakdown.Tests.Snowflake; [TestFixture] public class CommentTests { [Test] public void Parse_WithSingleLineCommentInSelect_PreservesComment() { // Arrange var sql = @"SELECT ID, NAME, -- This is a customer name EMAIL FROM USERS"; // Act var query = QueryBreakdown.Parse(sql); // Assert Assert.That(query.SelectClause.Clause, Does.Contain("ID")); Assert.That(query.SelectClause.Clause, Does.Contain("NAME")); Assert.Multiple(() => { Assert.That(query.SelectClause.Clause, Does.Contain("EMAIL")); Assert.That(query.SelectClause.Comment, Does.Contain("-- This is a customer name")); }); } [Test] public void Parse_WithMultiLineCommentInSelect_PreservesComment() { // Arrange var sql = @"SELECT ID, /* Multi-line comment explaining the query */ NAME, EMAIL FROM USERS"; // Act var query = QueryBreakdown.Parse(sql); // Assert Assert.That(query.SelectClause.Clause, Does.Contain("ID")); Assert.Multiple(() => { Assert.That(query.SelectClause.Clause, Does.Contain("NAME")); Assert.That(query.SelectClause.Comment, Does.Contain("/* Multi-line comment")); }); Assert.That(query.SelectClause.Comment, Does.Contain("explaining the query */")); } [Test] public void Parse_WithCommentsInMultipleClauses_PreservesAllComments() { // Arrange var sql = @"SELECT -- Select specific columns ID, NAME, EMAIL FROM USERS -- Main user table WHERE /* Active users only */ STATUS = 'Active' ORDER BY NAME -- Sort by name"; // Act var query = QueryBreakdown.Parse(sql); Assert.Multiple(() => { // Assert Assert.That(query.SelectClause.Comment, Does.Contain("-- Select specific columns")); Assert.That(query.FromClause.Comment, Does.Contain("-- Main user table")); Assert.That(query.WhereClause.Comment, Does.Contain("/* Active users only */")); Assert.That(query.OrderByClause.Comment, Does.Contain("-- Sort by name")); }); } [Test] public void GetSql_WithComments_ReturnsCommentsInOutput() { // Arrange var sql = @"SELECT -- Important columns ID, NAME FROM USERS -- User table WHERE STATUS = 'Active'"; var query = QueryBreakdown.Parse(sql); // Act var result = query.GetSql(); // Assert Assert.That(result, Does.Contain("-- Important columns")); Assert.That(result, Does.Contain("-- User table")); } [Test] public void Parse_WithNoComments_HasNullCommentProperties() { // Arrange var sql = "SELECT ID, NAME FROM USERS WHERE STATUS = 'Active'"; // Act var query = QueryBreakdown.Parse(sql); Assert.Multiple(() => { // Assert Assert.That(query.SelectClause.Comment, Is.Null.Or.Empty); Assert.That(query.FromClause.Comment, Is.Null.Or.Empty); Assert.That(query.WhereClause.Comment, Is.Null.Or.Empty); }); } [Test] public void Clone_WithComments_PreservesComments() { // Arrange var sql = @"SELECT -- Select columns ID, NAME FROM USERS WHERE STATUS = 'Active'"; var original = QueryBreakdown.Parse(sql); // Act var cloned = (QueryBreakdown)original.Clone(); Assert.Multiple(() => { // Assert Assert.That(cloned.SelectClause.Comment, Is.EqualTo(original.SelectClause.Comment)); Assert.That(cloned.FromClause.Comment, Is.EqualTo(original.FromClause.Comment)); Assert.That(cloned.WhereClause.Comment, Is.EqualTo(original.WhereClause.Comment)); }); } [Test] public void Parse_WithCommentInGroupBy_PreservesComment() { // Arrange var sql = @"SELECT DEPARTMENT, COUNT(*) AS EMPLOYEE_COUNT FROM EMPLOYEES GROUP BY -- Group by department DEPARTMENT"; // Act var query = QueryBreakdown.Parse(sql); // Assert Assert.That(query.GroupByClause.Comment, Does.Contain("-- Group by department")); } [Test] public void Parse_WithCommentInHaving_PreservesComment() { // Arrange var sql = @"SELECT DEPARTMENT, COUNT(*) AS EMPLOYEE_COUNT FROM EMPLOYEES GROUP BY DEPARTMENT HAVING /* Only departments with more than 10 employees */ COUNT(*) > 10"; // Act var query = QueryBreakdown.Parse(sql); // Assert Assert.That(query.HavingClause.Comment, Does.Contain("/* Only departments with more than 10 employees */")); } [Test] public void GetSql_RoundTrip_WithComments_PreservesComments() { // Arrange var sql = @"SELECT -- Customer details ID, NAME, EMAIL FROM USERS WHERE STATUS = 'Active'"; var query = QueryBreakdown.Parse(sql); // Act var generatedSql = query.GetSql(); var reparsed = QueryBreakdown.Parse(generatedSql); // Assert Assert.That(reparsed.SelectClause.Comment, Does.Contain("-- Customer details")); } [Test] public void Parse_WithMultipleCommentsInSameClause_PreservesAllComments() { // Arrange var sql = @"SELECT -- First comment ID, NAME, -- Second comment /* Third comment */ EMAIL FROM USERS"; // Act var query = QueryBreakdown.Parse(sql); // Assert Assert.That(query.SelectClause.Comment, Does.Contain("-- First comment")); Assert.That(query.SelectClause.Comment, Does.Contain("-- Second comment")); Assert.That(query.SelectClause.Comment, Does.Contain("/* Third comment */")); } [Test] public void ExtractSqlComments_WithMultipleCommentTypes_ExtractsAll() { // Arrange var sql = @"SELECT ID, -- Single line /* Multi line */ NAME FROM USERS"; // Act var parser = new Strata.SqlTools.Statements.Snowflake.StatementParser(); var cleanSql = parser.ExtractSqlComments(sql, out var comments); // Assert Assert.That(comments, Has.Count.EqualTo(2)); Assert.Multiple(() => { Assert.That(comments[0], Does.Contain("-- Single line")); Assert.That(comments[1], Does.Contain("/* Multi")); }); Assert.Multiple(() => { Assert.That(comments[1], Does.Contain("line */")); Assert.That(cleanSql, Does.Not.Contain("-- Single line")); }); Assert.That(cleanSql, Does.Not.Contain("/*")); } [Test] public void Demo_CompleteRoundTrip_WithComments() { // Arrange - Snowflake SQL with various comment styles var originalSql = @" SELECT -- Primary key ID, NAME, -- Customer name field /* Email address for notifications */ EMAIL, STATUS FROM USERS -- Main user table WHERE /* Filter for active users only */ STATUS = 'Active' ORDER BY NAME -- Sort alphabetically "; // Act - Parse SQL var query = QueryBreakdown.Parse(originalSql); // Assert - Comments are preserved in separate properties Assert.That(query.SelectClause.Clause, Does.Contain("ID")); Assert.That(query.SelectClause.Clause, Does.Contain("NAME")); Assert.That(query.SelectClause.Clause, Does.Contain("EMAIL")); Assert.That(query.SelectClause.Clause, Does.Not.Contain("--")); Assert.Multiple(() => { Assert.That(query.SelectClause.Clause, Does.Not.Contain("/*")); Assert.That(query.SelectClause.Comment, Does.Contain("-- Primary key")); }); Assert.That(query.SelectClause.Comment, Does.Contain("-- Customer name field")); Assert.Multiple(() => { Assert.That(query.SelectClause.Comment, Does.Contain("/* Email address for notifications */")); Assert.That(query.FromClause.Comment, Does.Contain("-- Main user table")); Assert.That(query.WhereClause.Comment, Does.Contain("/* Filter for active users only */")); Assert.That(query.OrderByClause.Comment, Does.Contain("-- Sort alphabetically")); }); // Act - Generate SQL var regeneratedSql = query.GetSql(); // Assert - Comments are included in output Assert.That(regeneratedSql, Does.Contain("-- Primary key")); Assert.That(regeneratedSql, Does.Contain("-- Customer name field")); Assert.That(regeneratedSql, Does.Contain("/* Email address for notifications */")); Assert.That(regeneratedSql, Does.Contain("-- Main user table")); Assert.That(regeneratedSql, Does.Contain("/* Filter for active users only */")); Assert.That(regeneratedSql, Does.Contain("-- Sort alphabetically")); // Display the generated SQL TestContext.WriteLine("Regenerated Snowflake SQL:"); TestContext.WriteLine(regeneratedSql); } [Test] public void Parse_WithDoubleQuotedIdentifiersAndComments_PreservesComments() { // Arrange - Snowflake-specific double-quoted identifiers var sql = @"SELECT -- Primary key column ""ID"", ""Name"", -- Customer name ""Email Address"" -- Email with space in column name FROM ""Users"""; // Act var query = QueryBreakdown.Parse(sql); // Assert Assert.That(query.SelectClause.Comment, Does.Contain("-- Primary key column")); Assert.That(query.SelectClause.Comment, Does.Contain("-- Customer name")); Assert.That(query.SelectClause.Comment, Does.Contain("-- Email with space in column name")); } [Test] public void Parse_WithSnowflakeParameterSyntaxAndComments_PreservesComments() { // Arrange - Snowflake :parameter syntax var sql = @"SELECT ID, NAME, EMAIL FROM USERS WHERE -- Filter by status parameter STATUS = :status AND -- Additional condition CREATED_DATE > :start_date"; // Act var query = QueryBreakdown.Parse(sql); query.SetParameterValue(":status", "Active"); query.SetParameterValue(":start_date", "2024-01-01"); // Assert Assert.That(query.WhereClause.Comment, Does.Contain("-- Filter by status parameter")); Assert.Multiple(() => { Assert.That(query.WhereClause.Comment, Does.Contain("-- Additional condition")); Assert.That(query.Parameters, Contains.Key(":status")); }); Assert.That(query.Parameters, Contains.Key(":start_date")); } [Test] public void Parse_WithQualifyClauseAndComments_PreservesComments() { // Arrange - Snowflake-specific QUALIFY clause var sql = @"SELECT ID, NAME, ROW_NUMBER() OVER (PARTITION BY DEPARTMENT ORDER BY SALARY DESC) AS RN FROM EMPLOYEES QUALIFY -- Get only the top earner per department RN = 1"; // Act var query = QueryBreakdown.Parse(sql); // Assert - Note: QUALIFY handling depends on implementation Assert.That(query.SelectClause.Clause, Does.Contain("ID")); Assert.That(query.SelectClause.Clause, Does.Contain("NAME")); } [Test] public void Parse_WithLimitClauseAndComments_PreservesComments() { // Arrange - Snowflake LIMIT syntax var sql = @"SELECT ID, NAME, EMAIL FROM USERS ORDER BY NAME LIMIT 100 -- Limit to first 100 records"; // Act var query = QueryBreakdown.Parse(sql); // Assert Assert.That(query.OrderByClause.Comment, Does.Contain("-- Limit to first 100 records")); } }