chore: initial git load of code space

This commit is contained in:
Thom Lamb
2026-05-12 08:52:33 -05:00
parent 9abada692f
commit 5e467bcc9c
384 changed files with 65960 additions and 2 deletions
@@ -0,0 +1,227 @@
using Strata.SqlTools.SqlBreakdown.Enums.SQL;
using Strata.SqlTools.SqlBreakdown.Exceptions;
using StatementReader = Strata.SqlTools.Statements.Snowflake.StatementReader;
namespace Strata.SqlTools.SqlBreakdown.Tests.Snowflake;
[TestFixture]
public class StatementReaderTests
{
[Test]
public void StatementReader_ParsesCalculationString()
{
// Arrange
var calculationString = "(1 + 2) / SUM([586883]) + SUM([586664]) - SUM([586664_1]) * 2.3";
var sqlReader = new StatementReader(calculationString);
var tokens = new List<(TokenType Type, string Value)>();
// Act
while (sqlReader.Read())
{
tokens.Add((sqlReader.TokenType, sqlReader.TokenValue));
}
// Assert
Assert.That(tokens, Is.Not.Empty);
Assert.That(tokens[0].Type, Is.EqualTo(TokenType.LeftParenthesis));
Assert.That(tokens[1].Type, Is.EqualTo(TokenType.Number));
Assert.That(tokens[1].Value, Is.EqualTo("1"));
}
[Test]
public void StatementReader_ParsesDoubleQuotedIdentifiers()
{
// Arrange - Snowflake-specific double-quoted identifiers
var calculationString = "\"COLUMN_1\" + \"COLUMN_2\" * 2";
var sqlReader = new StatementReader(calculationString);
var tokens = new List<(TokenType Type, string Value)>();
// Act
while (sqlReader.Read())
{
tokens.Add((sqlReader.TokenType, sqlReader.TokenValue));
}
// Assert
Assert.That(tokens, Has.Count.EqualTo(5)); // "COLUMN_1" + "COLUMN_2" * 2
Assert.That(tokens[0].Type, Is.EqualTo(TokenType.ColumnIdentifier));
Assert.That(tokens[0].Value, Is.EqualTo("COLUMN_1"));
Assert.That(tokens[1].Type, Is.EqualTo(TokenType.Plus));
Assert.That(tokens[2].Type, Is.EqualTo(TokenType.ColumnIdentifier));
Assert.That(tokens[2].Value, Is.EqualTo("COLUMN_2"));
Assert.That(tokens[3].Type, Is.EqualTo(TokenType.Multiply));
Assert.That(tokens[4].Type, Is.EqualTo(TokenType.Number));
Assert.That(tokens[4].Value, Is.EqualTo("2"));
}
[Test]
public void StatementReader_ParsesMixedIdentifierTypes()
{
// Arrange - Mix of double-quoted and square-bracketed identifiers
var calculationString = "\"REVENUE\" + [COST] - PROFIT";
var sqlReader = new StatementReader(calculationString);
var tokens = new List<(TokenType Type, string Value)>();
// Act
while (sqlReader.Read())
{
tokens.Add((sqlReader.TokenType, sqlReader.TokenValue));
}
// Assert
Assert.That(tokens, Has.Count.EqualTo(5));
Assert.That(tokens[0].Type, Is.EqualTo(TokenType.ColumnIdentifier));
Assert.That(tokens[0].Value, Is.EqualTo("REVENUE"));
Assert.That(tokens[1].Type, Is.EqualTo(TokenType.Plus));
Assert.That(tokens[2].Type, Is.EqualTo(TokenType.ColumnIdentifier));
Assert.That(tokens[2].Value, Is.EqualTo("COST"));
Assert.That(tokens[3].Type, Is.EqualTo(TokenType.Minus));
Assert.That(tokens[4].Type, Is.EqualTo(TokenType.String));
Assert.That(tokens[4].Value, Is.EqualTo("PROFIT"));
}
[Test]
public void StatementReader_ParsesFunctionWithDoubleQuotedColumn()
{
// Arrange
var calculationString = "SUM(\"TOTAL_AMOUNT\") / COUNT(\"ID\")";
var sqlReader = new StatementReader(calculationString);
var tokens = new List<(TokenType Type, string Value)>();
// Act
while (sqlReader.Read())
{
tokens.Add((sqlReader.TokenType, sqlReader.TokenValue));
}
// Assert
Assert.That(tokens, Is.Not.Empty);
Assert.That(tokens[0].Type, Is.EqualTo(TokenType.FunctionStart));
Assert.That(tokens[0].Value, Is.EqualTo("SUM"));
Assert.That(tokens[1].Type, Is.EqualTo(TokenType.ColumnIdentifier));
Assert.That(tokens[1].Value, Is.EqualTo("TOTAL_AMOUNT"));
Assert.That(tokens[2].Type, Is.EqualTo(TokenType.FunctionEnd));
}
[Test]
public void StatementReader_ParsesNumericIdentifiersWithUnderscores()
{
// Arrange - Column identifiers starting with numbers (e.g., "3_REVENUE")
var calculationString = "3_REVENUE + 4_COST - 5_PROFIT";
var sqlReader = new StatementReader(calculationString);
var tokens = new List<(TokenType Type, string Value)>();
// Act
while (sqlReader.Read())
{
tokens.Add((sqlReader.TokenType, sqlReader.TokenValue));
}
// Assert
Assert.That(tokens, Has.Count.EqualTo(5));
Assert.That(tokens[0].Type, Is.EqualTo(TokenType.ColumnIdentifier));
Assert.That(tokens[0].Value, Is.EqualTo("3_REVENUE"));
Assert.That(tokens[1].Type, Is.EqualTo(TokenType.Plus));
Assert.That(tokens[2].Type, Is.EqualTo(TokenType.ColumnIdentifier));
Assert.That(tokens[2].Value, Is.EqualTo("4_COST"));
Assert.That(tokens[3].Type, Is.EqualTo(TokenType.Minus));
Assert.That(tokens[4].Type, Is.EqualTo(TokenType.ColumnIdentifier));
Assert.That(tokens[4].Value, Is.EqualTo("5_PROFIT"));
}
[Test]
public void StatementReader_ParsesDecimalNumbers()
{
// Arrange
var calculationString = "123.45 + 67.89";
var sqlReader = new StatementReader(calculationString);
var tokens = new List<(TokenType Type, string Value)>();
// Act
while (sqlReader.Read())
{
tokens.Add((sqlReader.TokenType, sqlReader.TokenValue));
}
// Assert
Assert.That(tokens, Has.Count.EqualTo(3));
Assert.That(tokens[0].Type, Is.EqualTo(TokenType.Number));
Assert.That(tokens[0].Value, Is.EqualTo("123.45"));
Assert.That(tokens[1].Type, Is.EqualTo(TokenType.Plus));
Assert.That(tokens[2].Type, Is.EqualTo(TokenType.Number));
Assert.That(tokens[2].Value, Is.EqualTo("67.89"));
}
[Test]
public void StatementReader_ParsesUppercaseIdentifiers()
{
// Arrange - Snowflake conventionally uses uppercase for identifiers
var calculationString = "REVENUE + COST";
var sqlReader = new StatementReader(calculationString);
var tokens = new List<(TokenType Type, string Value)>();
// Act
while (sqlReader.Read())
{
tokens.Add((sqlReader.TokenType, sqlReader.TokenValue));
}
// Assert
Assert.That(tokens, Has.Count.EqualTo(3));
Assert.That(tokens[0].Type, Is.EqualTo(TokenType.String));
Assert.That(tokens[0].Value, Is.EqualTo("REVENUE"));
Assert.That(tokens[1].Type, Is.EqualTo(TokenType.Plus));
Assert.That(tokens[2].Type, Is.EqualTo(TokenType.String));
Assert.That(tokens[2].Value, Is.EqualTo("COST"));
}
[Test]
public void StatementReader_HandlesEmptyString()
{
// Arrange & Act & Assert
Assert.Throws<ArgumentNullException>(() => new StatementReader(""));
}
[Test]
public void StatementReader_ThrowsOnUnclosedDoubleQuote()
{
// Arrange
var calculationString = "\"COLUMN_NAME + 5";
var sqlReader = new StatementReader(calculationString);
// Act & Assert
var ex = Assert.Throws<InvalidSyntaxException>(() =>
{
while (sqlReader.Read())
{
// Read all tokens
}
});
Assert.That(ex!.Message, Does.Contain("Expected closing double quote"));
}
[Test]
public void StatementReader_ParsesNestedFunctions()
{
// Arrange
var calculationString = "SUM(AVG(\"REVENUE\"))";
var sqlReader = new StatementReader(calculationString);
var tokens = new List<(TokenType Type, string Value)>();
// Act
while (sqlReader.Read())
{
tokens.Add((sqlReader.TokenType, sqlReader.TokenValue));
}
// Assert
Assert.That(tokens, Is.Not.Empty);
Assert.That(tokens[0].Type, Is.EqualTo(TokenType.FunctionStart));
Assert.That(tokens[0].Value, Is.EqualTo("SUM"));
Assert.That(tokens[1].Type, Is.EqualTo(TokenType.FunctionStart));
Assert.That(tokens[1].Value, Is.EqualTo("AVG"));
Assert.That(tokens[2].Type, Is.EqualTo(TokenType.ColumnIdentifier));
Assert.That(tokens[2].Value, Is.EqualTo("REVENUE"));
}
}