Driven by `dotnet format analyzers --diagnostics NUnit2045`. The fixer
groups consecutive independent `Assert.That(...)` calls into
`Assert.Multiple(() => { ... })`, so a failing assertion no longer
short-circuits the block — every failure inside the group is reported,
which gives much better diagnostics on multi-property tests.
Audit confirmed no Assert.Throws / Assert.Fail / Assert.Catch / Assert.Pass
/ Assert.DoesNotThrow got pulled inside a Multiple block (those need to
short-circuit). All 1180 tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
405 lines
13 KiB
C#
405 lines
13 KiB
C#
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"));
|
|
}
|
|
|
|
}
|