chore: initial git load of code space
This commit is contained in:
@@ -0,0 +1,374 @@
|
||||
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.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.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
|
||||
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
|
||||
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
|
||||
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.That(comments[0], Does.Contain("-- Single line"));
|
||||
Assert.That(comments[1], Does.Contain("/* Multi"));
|
||||
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.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.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.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"));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user