Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbedea3941 |
@@ -41,6 +41,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Strata.SqlTools.SqlBreakdow
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Strata.SqlTools.Query", "src\Strata.SqlTools.Query\Strata.SqlTools.Query.csproj", "{177F3799-6A91-477B-87CC-BCCE05B87E1C}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests.Integration", "Tests.Integration", "{CFCF0678-C587-40E9-B0AC-A7082AEBF206}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
using Strata.SqlTools.Breakdowns.Snowflake;
|
||||
|
||||
namespace Strata.SqlTools.SqlBreakdown.Tests.Snowflake;
|
||||
|
||||
[TestFixture]
|
||||
public class DeleteBreakdownTests
|
||||
{
|
||||
#region Constructor Tests
|
||||
|
||||
[Test]
|
||||
public void Constructor_Default_InitializesEmptyClauses()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new DeleteBreakdown();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.FromClause.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.WhereClause.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.IsUsingWhereClause, Is.False);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Constructor_WithClauses_SetsProperties()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new DeleteBreakdown("USERS", "ID = :ID");
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.FromClause.Clause, Is.EqualTo("USERS"));
|
||||
Assert.That(breakdown.WhereClause.Clause, Is.EqualTo("ID = :ID"));
|
||||
Assert.That(breakdown.IsUsingWhereClause, Is.True);
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetSql Tests
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithWhere_RendersDeleteFromWhere()
|
||||
{
|
||||
// Arrange - Snowflake overrides the formatter with simplified DELETE FROM syntax
|
||||
var breakdown = new DeleteBreakdown("USERS", "ID = :ID");
|
||||
|
||||
// Act
|
||||
var sql = breakdown.GetSql();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(sql, Does.Contain("DELETE FROM"));
|
||||
Assert.That(sql, Does.Contain("USERS"));
|
||||
Assert.That(sql, Does.Contain("WHERE"));
|
||||
Assert.That(sql, Does.Contain("ID = :ID"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithoutWhere_OmitsWhereKeyword()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new DeleteBreakdown("USERS", string.Empty);
|
||||
|
||||
// Act
|
||||
var sql = breakdown.GetSql();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(sql, Does.Contain("DELETE FROM"));
|
||||
Assert.That(sql, Does.Not.Contain("WHERE"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Parse Tests
|
||||
|
||||
[Test]
|
||||
public void Parse_SnowflakeDelete_PopulatesClauses()
|
||||
{
|
||||
// Arrange
|
||||
var input = "DELETE FROM USERS WHERE ID = 1";
|
||||
|
||||
// Act
|
||||
var breakdown = DeleteBreakdown.Parse(input);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.FromClause.Clause, Is.EqualTo("USERS"));
|
||||
Assert.That(breakdown.WhereClause.Clause, Is.EqualTo("ID = 1"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_DeleteWithoutWhere_LeavesWhereEmpty()
|
||||
{
|
||||
// Act
|
||||
var breakdown = DeleteBreakdown.Parse("DELETE FROM USERS");
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.FromClause.Clause, Is.EqualTo("USERS"));
|
||||
Assert.That(breakdown.IsUsingWhereClause, Is.False);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_MicrosoftSqlMode_DelegatesToBase()
|
||||
{
|
||||
// Act - T-SQL DELETE with alias is supported through the base breakdown
|
||||
var breakdown = DeleteBreakdown.Parse("DELETE FROM Users WHERE Id = 1", isMicrosoftSql: true);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown, Is.InstanceOf<DeleteBreakdown>());
|
||||
Assert.That(breakdown.FromClause.Clause, Is.EqualTo("Users"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NullOrWhitespace_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => DeleteBreakdown.Parse(null!));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NotADeleteStatement_ThrowsFormatException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<FormatException>(() => DeleteBreakdown.Parse("SELECT * FROM USERS"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_MicrosoftSqlMode_ReturnsSnowflakeInstance()
|
||||
{
|
||||
// Act
|
||||
var success = DeleteBreakdown.TryParse("DELETE FROM Users WHERE Id = 1", out var breakdown, isMicrosoftSql: true);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.True);
|
||||
Assert.That(breakdown, Is.InstanceOf<DeleteBreakdown>());
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_WrongPrefix_ReturnsFalse()
|
||||
{
|
||||
// Act
|
||||
var success = DeleteBreakdown.TryParse("UPDATE USERS SET ID = 1", out _, out var error);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.False);
|
||||
Assert.That(error, Does.Contain("DELETE"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
using Strata.SqlTools.Breakdowns.Snowflake;
|
||||
|
||||
namespace Strata.SqlTools.SqlBreakdown.Tests.Snowflake;
|
||||
|
||||
[TestFixture]
|
||||
public class InsertBreakdownTests
|
||||
{
|
||||
#region Constructor Tests
|
||||
|
||||
[Test]
|
||||
public void Constructor_Default_InitializesEmptyClauses()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new InsertBreakdown();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.InsertIntoClause.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.ValuesClause.Clause, Is.EqualTo(string.Empty));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Constructor_WithClauses_SetsProperties()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new InsertBreakdown("USERS", "ID, NAME", ":ID, :NAME");
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("USERS"));
|
||||
Assert.That(breakdown.InsertIntoClause.Clause, Is.EqualTo("ID, NAME"));
|
||||
Assert.That(breakdown.ValuesClause.Clause, Is.EqualTo(":ID, :NAME"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Constructor_WithColumnNames_GeneratesColonPrefixedParameters()
|
||||
{
|
||||
// Arrange & Act - Snowflake uses :parameter syntax (vs SQL Server's @parameter)
|
||||
var breakdown = new InsertBreakdown("USERS", new List<string> { "ID", "NAME" });
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.InsertIntoClause.Clause, Is.EqualTo("[ID],[NAME]"));
|
||||
Assert.That(breakdown.ValuesClause.Clause, Is.EqualTo(":ID,:NAME"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Parse Tests
|
||||
|
||||
[Test]
|
||||
public void Parse_SnowflakeInsert_PopulatesClauses()
|
||||
{
|
||||
// Arrange
|
||||
var input = "INSERT INTO USERS (ID, NAME) VALUES (1, 'BOB')";
|
||||
|
||||
// Act
|
||||
var breakdown = InsertBreakdown.Parse(input);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("USERS"));
|
||||
Assert.That(breakdown.InsertIntoClause.Clause, Is.EqualTo("ID, NAME"));
|
||||
Assert.That(breakdown.ValuesClause.Clause, Is.EqualTo("1, 'BOB'"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_MicrosoftSqlMode_DelegatesToBaseAndSucceeds()
|
||||
{
|
||||
// Arrange
|
||||
var input = "INSERT INTO Users (Id) VALUES (1)";
|
||||
|
||||
// Act
|
||||
var breakdown = InsertBreakdown.Parse(input, isMicrosoftSql: true);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown, Is.InstanceOf<InsertBreakdown>());
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("Users"));
|
||||
Assert.That(breakdown.InsertIntoClause.Clause, Is.EqualTo("Id"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NullOrWhitespace_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => InsertBreakdown.Parse(" "));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NotAnInsertStatement_ThrowsFormatException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<FormatException>(() => InsertBreakdown.Parse("SELECT * FROM USERS"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_ValidInsert_ReturnsTrue()
|
||||
{
|
||||
// Act
|
||||
var success = InsertBreakdown.TryParse("INSERT INTO USERS (ID) VALUES (1)", out var breakdown);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.True);
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("USERS"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_MicrosoftSqlMode_ReturnsSnowflakeInstance()
|
||||
{
|
||||
// Act
|
||||
var success = InsertBreakdown.TryParse("INSERT INTO Users (Id) VALUES (1)", out var breakdown, isMicrosoftSql: true);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.True);
|
||||
Assert.That(breakdown, Is.InstanceOf<InsertBreakdown>());
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_WrongPrefix_ReturnsFalse()
|
||||
{
|
||||
// Act
|
||||
var success = InsertBreakdown.TryParse("DELETE FROM USERS", out _, out var error);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.False);
|
||||
Assert.That(error, Does.Contain("INSERT INTO"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
using Strata.SqlTools.Breakdowns.Snowflake;
|
||||
|
||||
namespace Strata.SqlTools.SqlBreakdown.Tests.Snowflake;
|
||||
|
||||
[TestFixture]
|
||||
public class ProcedureBreakdownTests
|
||||
{
|
||||
#region Constructor Tests
|
||||
|
||||
[Test]
|
||||
public void Constructor_WithName_SetsProcedureName()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new ProcedureBreakdown("MY_PROC");
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.ProcedureName.Clause, Is.EqualTo("MY_PROC"));
|
||||
Assert.That(breakdown.IsUsingParameters, Is.False);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Constructor_WithParameters_SetsParameters()
|
||||
{
|
||||
// Arrange
|
||||
var parameters = new Dictionary<string, string> { ["@ID"] = "1" };
|
||||
|
||||
// Act
|
||||
var breakdown = new ProcedureBreakdown("MY_PROC", parameters);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.IsUsingParameters, Is.True);
|
||||
Assert.That(breakdown.Parameters["@ID"], Is.EqualTo("1"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetSql Tests - Snowflake CALL Syntax
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithoutParameters_RendersCallWithEmptyParens()
|
||||
{
|
||||
// Arrange - Snowflake uses CALL proc() rather than EXEC proc
|
||||
var breakdown = new ProcedureBreakdown("MY_PROC");
|
||||
|
||||
// Act
|
||||
var sql = breakdown.GetSql();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(sql, Does.Contain("CALL"));
|
||||
Assert.That(sql, Does.Contain("MY_PROC"));
|
||||
Assert.That(sql, Does.Contain("()"));
|
||||
Assert.That(sql, Does.Not.Contain("EXEC"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithParameters_RendersNamedArrowSyntax()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new ProcedureBreakdown("MY_PROC");
|
||||
breakdown.AddParameter("@ID", "1");
|
||||
|
||||
// Act - Snowflake named-parameter syntax strips @ and uses =>
|
||||
var sql = breakdown.GetSql();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(sql, Does.Contain("CALL"));
|
||||
Assert.That(sql, Does.Contain("ID => 1"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Parse Tests - Snowflake CALL
|
||||
|
||||
[Test]
|
||||
public void Parse_CallWithoutParameters_PopulatesName()
|
||||
{
|
||||
// Act
|
||||
var breakdown = ProcedureBreakdown.Parse("CALL MY_PROC()");
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.ProcedureName.Clause, Is.EqualTo("MY_PROC"));
|
||||
Assert.That(breakdown.IsUsingParameters, Is.False);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_CallWithNamedParameters_PopulatesParametersWithAtPrefix()
|
||||
{
|
||||
// Arrange
|
||||
var input = "CALL MY_PROC(ID => 1, NAME => 'BOB')";
|
||||
|
||||
// Act
|
||||
var breakdown = ProcedureBreakdown.Parse(input);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert - parsed named params are stored with @ prefix for consistency
|
||||
Assert.That(breakdown.ProcedureName.Clause, Is.EqualTo("MY_PROC"));
|
||||
Assert.That(breakdown.Parameters["@ID"], Is.EqualTo("1"));
|
||||
Assert.That(breakdown.Parameters["@NAME"], Is.EqualTo("'BOB'"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_CallWithPositionalParameters_GeneratesParamNames()
|
||||
{
|
||||
// Arrange - no => present, so values are treated positionally
|
||||
var input = "CALL MY_PROC(1, 'BOB')";
|
||||
|
||||
// Act
|
||||
var breakdown = ProcedureBreakdown.Parse(input);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.Parameters["@param1"], Is.EqualTo("1"));
|
||||
Assert.That(breakdown.Parameters["@param2"], Is.EqualTo("'BOB'"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_MicrosoftSqlMode_AcceptsExecSyntax()
|
||||
{
|
||||
// Act - T-SQL EXEC is parsed via base-class delegation
|
||||
var breakdown = ProcedureBreakdown.Parse("EXEC dbo.GetUser @Id = 1", isMicrosoftSql: true);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown, Is.InstanceOf<ProcedureBreakdown>());
|
||||
Assert.That(breakdown.ProcedureName.Clause, Is.EqualTo("dbo.GetUser"));
|
||||
Assert.That(breakdown.Parameters["@Id"], Is.EqualTo("1"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NullOrWhitespace_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => ProcedureBreakdown.Parse(" "));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NotACallStatement_ThrowsFormatException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<FormatException>(() => ProcedureBreakdown.Parse("SELECT * FROM USERS"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_ValidCall_ReturnsTrue()
|
||||
{
|
||||
// Act
|
||||
var success = ProcedureBreakdown.TryParse("CALL MY_PROC()", out var breakdown);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.True);
|
||||
Assert.That(breakdown.ProcedureName.Clause, Is.EqualTo("MY_PROC"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_WrongPrefix_ReturnsFalseWithMessage()
|
||||
{
|
||||
// Act
|
||||
var success = ProcedureBreakdown.TryParse("SELECT 1", out _, out var error);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.False);
|
||||
Assert.That(error, Does.Contain("CALL"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
using Strata.SqlTools.Breakdowns.Snowflake;
|
||||
|
||||
namespace Strata.SqlTools.SqlBreakdown.Tests.Snowflake;
|
||||
|
||||
[TestFixture]
|
||||
public class UpdateBreakdownTests
|
||||
{
|
||||
#region Constructor Tests
|
||||
|
||||
[Test]
|
||||
public void Constructor_Default_InitializesEmptyClauses()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new UpdateBreakdown();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.SetClause.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.IsUsingWhereClause, Is.False);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Constructor_WithClauses_SetsProperties()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new UpdateBreakdown("USERS", "NAME = :NAME", "ID = :ID");
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("USERS"));
|
||||
Assert.That(breakdown.SetClause.Clause, Is.EqualTo("NAME = :NAME"));
|
||||
Assert.That(breakdown.WhereClause.Clause, Is.EqualTo("ID = :ID"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetSql Tests
|
||||
|
||||
[Test]
|
||||
public void GetSql_RendersUpdateSetWhere()
|
||||
{
|
||||
// Arrange - Snowflake inherits the SQL Server UPDATE formatter
|
||||
var breakdown = new UpdateBreakdown("USERS", "NAME = :NAME", "ID = :ID");
|
||||
|
||||
// Act
|
||||
var sql = breakdown.GetSql();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(sql, Does.Contain("UPDATE"));
|
||||
Assert.That(sql, Does.Contain("USERS"));
|
||||
Assert.That(sql, Does.Contain("SET"));
|
||||
Assert.That(sql, Does.Contain("NAME = :NAME"));
|
||||
Assert.That(sql, Does.Contain("WHERE"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Parse Tests
|
||||
|
||||
[Test]
|
||||
public void Parse_SnowflakeUpdate_PopulatesClauses()
|
||||
{
|
||||
// Arrange
|
||||
var input = "UPDATE USERS SET NAME = 'BOB' WHERE ID = 1";
|
||||
|
||||
// Act
|
||||
var breakdown = UpdateBreakdown.Parse(input);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("USERS"));
|
||||
Assert.That(breakdown.SetClause.Clause, Is.EqualTo("NAME = 'BOB'"));
|
||||
Assert.That(breakdown.WhereClause.Clause, Is.EqualTo("ID = 1"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_UpdateWithFrom_PopulatesFromClause()
|
||||
{
|
||||
// Arrange
|
||||
var input = "UPDATE T SET T.NAME = S.NAME FROM TARGET T INNER JOIN SOURCE S ON T.ID = S.ID WHERE S.ACTIVE = 1";
|
||||
|
||||
// Act
|
||||
var breakdown = UpdateBreakdown.Parse(input);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.IsUsingFromClause, Is.True);
|
||||
Assert.That(breakdown.FromClause.Clause, Does.Contain("INNER JOIN SOURCE"));
|
||||
Assert.That(breakdown.WhereClause.Clause, Is.EqualTo("S.ACTIVE = 1"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_MicrosoftSqlMode_DelegatesToBase()
|
||||
{
|
||||
// Act
|
||||
var breakdown = UpdateBreakdown.Parse("UPDATE Users SET Name = 'Bob' WHERE Id = 1", isMicrosoftSql: true);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown, Is.InstanceOf<UpdateBreakdown>());
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("Users"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NullOrWhitespace_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => UpdateBreakdown.Parse(string.Empty));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NotAnUpdateStatement_ThrowsFormatException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<FormatException>(() => UpdateBreakdown.Parse("SELECT * FROM USERS"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_MicrosoftSqlMode_ReturnsSnowflakeInstance()
|
||||
{
|
||||
// Act
|
||||
var success = UpdateBreakdown.TryParse("UPDATE Users SET Name = 'Bob'", out var breakdown, isMicrosoftSql: true);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.True);
|
||||
Assert.That(breakdown, Is.InstanceOf<UpdateBreakdown>());
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_WrongPrefix_ReturnsFalse()
|
||||
{
|
||||
// Act
|
||||
var success = UpdateBreakdown.TryParse("DELETE FROM USERS", out _, out var error);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.False);
|
||||
Assert.That(error, Does.Contain("UPDATE"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
using System.Collections;
|
||||
using Strata.SqlTools.SqlBreakdown.Utilities;
|
||||
|
||||
namespace Strata.SqlTools.SqlBreakdown.Tests.Utilities;
|
||||
|
||||
[TestFixture]
|
||||
public class ArrayUtilsTests
|
||||
{
|
||||
private static readonly Guid GuidA = new("11111111-1111-1111-1111-111111111111");
|
||||
private static readonly Guid GuidB = new("22222222-2222-2222-2222-222222222222");
|
||||
private static readonly Guid GuidC = new("33333333-3333-3333-3333-333333333333");
|
||||
|
||||
#region NewArray / Coalesce
|
||||
|
||||
[Test]
|
||||
public void NewArray_ReturnsArrayOfValues()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.NewArray(1, 2, 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(new[] { 1, 2, 3 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Coalesce_ReturnsFirstNonNull()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(ArrayUtils.Coalesce(null!, null!, "x", "y"), Is.EqualTo("x"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Coalesce_AllNull_ReturnsNull()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(ArrayUtils.Coalesce(null!, null!), Is.Null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CSV -> Collection
|
||||
|
||||
[Test]
|
||||
public void GetArrayListFromCsv_TrimsAndSplits()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.GetArrayListFromCsv("a, b, c");
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(new ArrayList { "a", "b", "c" }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetArrayListFromCsv_Empty_ReturnsEmptyList()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(ArrayUtils.GetArrayListFromCsv(string.Empty), Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetGenericListFromCsv_TrimsEntries()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.GetGenericListFromCsv("a, b ,c");
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(new List<string> { "a", "b", "c" }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetGenericListFromCsv_Empty_ReturnsEmpty()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(ArrayUtils.GetGenericListFromCsv(string.Empty), Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetIntegerListFromCsv_SkipsNonIntegers()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.GetIntegerListFromCsv("1,2,x,3");
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(new List<int> { 1, 2, 3 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetGuidListFromCsv_ParsesValidSkipsInvalid()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.GetGuidListFromCsv($"{GuidA},not-a-guid,{GuidB}");
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(new List<Guid> { GuidA, GuidB }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetGuidListFromCsv_Empty_ReturnsEmpty()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(ArrayUtils.GetGuidListFromCsv(string.Empty), Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetGuidArrayFromCsv_ParsesGuids()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.GetGuidArrayFromCsv($"{GuidA},{GuidB}");
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(new[] { GuidA, GuidB }));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Collection -> CSV
|
||||
|
||||
[Test]
|
||||
public void GetCsvFromArrayList_JoinsWithCommas()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.GetCsvFromArrayList(new ArrayList { "a", "b", "c" });
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("a,b,c"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetCsvFromGenericList_JoinsWithCommas()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(ArrayUtils.GetCsvFromGenericList(new List<string> { "a", "b" }), Is.EqualTo("a,b"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetCsvFromGenericList_SingleQuotes_WrapsEachValue()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.GetCsvFromGenericList(new List<string> { "a", "b" }, ArrayUtils.QuoteType.Single);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("'a','b'"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetCsvFromGenericList_DoubleQuotes_WrapsEachValue()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.GetCsvFromGenericList(new List<string> { "a", "b" }, ArrayUtils.QuoteType.Double);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("\"a\",\"b\""));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetCsvFromGenericList_NoneQuoteType_BehavesLikePlainJoin()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(ArrayUtils.GetCsvFromGenericList(new List<string> { "a", "b" }, ArrayUtils.QuoteType.None), Is.EqualTo("a,b"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetCsvFromGenericListOfGuids_Null_ReturnsEmpty()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(ArrayUtils.GetCsvFromGenericListOfGuids(null!), Is.EqualTo(string.Empty));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetCsvFromGenericListOfGuids_NoQuotes_JoinsGuids()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.GetCsvFromGenericListOfGuids(new List<Guid> { GuidA, GuidB });
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo($"{GuidA},{GuidB}"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetCsvFromGenericListOfGuids_SingleQuotes_WrapsEachGuid()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.GetCsvFromGenericListOfGuids(new List<Guid> { GuidA }, ArrayUtils.QuoteType.Single);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo($"'{GuidA}'"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Encode
|
||||
|
||||
[Test]
|
||||
public void Encode_NoInternalDelimiters_JoinsWithCommas()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(ArrayUtils.Encode(new List<string> { "x", "y", "z" }), Is.EqualTo("x,y,z"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Encode_InternalComma_ReplacedWithIllegalCharacter()
|
||||
{
|
||||
// Arrange - internal commas are swapped for char(8) so they survive the comma join
|
||||
const char illegal = (char)8;
|
||||
|
||||
// Act
|
||||
var result = ArrayUtils.Encode(new List<string> { "a,b", "c" });
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo($"a{illegal}b,c"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Guid List <-> String
|
||||
|
||||
[Test]
|
||||
public void ConvertGuidStringToList_Empty_ReturnsEmpty()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(ArrayUtils.ConvertGuidStringToList(string.Empty), Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertGuidStringToList_ParsesAll()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.ConvertGuidStringToList($"{GuidA},{GuidB}");
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(new List<Guid> { GuidA, GuidB }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertToGuidArray_ParsesStrings()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.ConvertToGuidArray(new[] { GuidA.ToString(), GuidB.ToString() });
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(new[] { GuidA, GuidB }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertToGuidList_ParsesStrings()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.ConvertToGuidList(new[] { GuidA.ToString() });
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(new List<Guid> { GuidA }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertGuidListToString_Null_ReturnsEmpty()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(ArrayUtils.ConvertGuidListToString(null!), Is.EqualTo(string.Empty));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertGuidListToString_NoSurround_JoinsWithCommas()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(ArrayUtils.ConvertGuidListToString(new[] { GuidA, GuidB }), Is.EqualTo($"{GuidA},{GuidB}"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertGuidListToString_WithSurroundChar_WrapsEachGuid()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.ConvertGuidListToString(new[] { GuidA }, "'");
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo($"'{GuidA}'"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertGuidListToStringList_ReturnsStringRepresentations()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.ConvertGuidListToStringList(new[] { GuidA, GuidB });
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(new List<string> { GuidA.ToString(), GuidB.ToString() }));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Intersection
|
||||
|
||||
[Test]
|
||||
public void GetGuidListsIntersection_ReturnsCommonGuids()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.GetGuidListsIntersection(
|
||||
new List<Guid> { GuidA, GuidB },
|
||||
new List<Guid> { GuidB, GuidC });
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(new List<Guid> { GuidB }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetGuidListsIntersection_NoOverlap_ReturnsEmpty()
|
||||
{
|
||||
// Act
|
||||
var result = ArrayUtils.GetGuidListsIntersection(
|
||||
new List<Guid> { GuidA },
|
||||
new List<Guid> { GuidB });
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetGuidListsIntersection_NullArguments_ReturnEmpty()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(ArrayUtils.GetGuidListsIntersection(null!, null!), Is.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
using Strata.SqlTools.SqlBreakdown.Utilities;
|
||||
|
||||
namespace Strata.SqlTools.SqlBreakdown.Tests.Utilities;
|
||||
|
||||
[TestFixture]
|
||||
public class GuidUtilsTests
|
||||
{
|
||||
private static readonly Guid Sample = new("0123abcd-4567-89ef-0123-456789abcdef");
|
||||
|
||||
#region TranslateGuid / UnTranslateGuid
|
||||
|
||||
[Test]
|
||||
public void TranslateGuid_RemovesHyphensAndPrefixesWithG()
|
||||
{
|
||||
// Act
|
||||
var result = GuidUtils.TranslateGuid(Sample);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(result, Does.StartWith("g"));
|
||||
Assert.That(result, Has.Length.EqualTo(33));
|
||||
Assert.That(result, Does.Not.Contain("-"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnTranslateGuid_RoundTripsTranslateGuid()
|
||||
{
|
||||
// Arrange
|
||||
var translated = GuidUtils.TranslateGuid(Sample);
|
||||
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.UnTranslateGuid(translated), Is.EqualTo(Sample));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnTranslateGuid_AlreadyHyphenated_ParsesDirectly()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.UnTranslateGuid(Sample.ToString()), Is.EqualTo(Sample));
|
||||
}
|
||||
|
||||
[TestCase("")] // null/empty guard
|
||||
[TestCase("notprefixed")] // no hyphen, does not start with 'g'
|
||||
[TestCase("gTOOSHORT")] // starts with 'g' but wrong length (not 33)
|
||||
public void UnTranslateGuid_InvalidInputs_ReturnEmpty(string value)
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.UnTranslateGuid(value), Is.EqualTo(Guid.Empty));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SQL-safe column GUID
|
||||
|
||||
[Test]
|
||||
public void GetSqlColumnSafeGuid_UppercasesAndReplacesHyphens()
|
||||
{
|
||||
// Act
|
||||
var result = GuidUtils.GetSqlColumnSafeGuid(Sample);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(result, Does.StartWith("G"));
|
||||
Assert.That(result, Does.Not.Contain("-"));
|
||||
Assert.That(result, Does.Contain("_"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetGuidFromSqlColumnSafeGuid_RoundTrips()
|
||||
{
|
||||
// Arrange
|
||||
var safe = GuidUtils.GetSqlColumnSafeGuid(Sample);
|
||||
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.GetGuidFromSqlColumnSafeGuid(safe), Is.EqualTo(Sample));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TranslateTextToGuid
|
||||
|
||||
[Test]
|
||||
public void TranslateTextToGuid_IsDeterministic()
|
||||
{
|
||||
// Act & Assert - same input must always yield the same GUID
|
||||
Assert.That(GuidUtils.TranslateTextToGuid("hello world"), Is.EqualTo(GuidUtils.TranslateTextToGuid("hello world")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TranslateTextToGuid_EmptyInput_ReturnsEmpty()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.TranslateTextToGuid(string.Empty), Is.EqualTo(Guid.Empty));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TranslateTextToGuid_DifferentInputs_GenerallyDiffer()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.TranslateTextToGuid("alpha"), Is.Not.EqualTo(GuidUtils.TranslateTextToGuid("beta")));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Validation
|
||||
|
||||
[TestCase("0123abcd-4567-89ef-0123-456789abcdef", true)]
|
||||
[TestCase("not a guid", false)]
|
||||
[TestCase("", false)]
|
||||
public void IsGuid_String_ValidatesCorrectly(string value, bool expected)
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.IsGuid(value), Is.EqualTo(expected));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsGuid_Object_GuidInstance_ReturnsTrue()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.IsGuid((object)Sample), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsGuid_Object_GuidString_ReturnsTrue()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.IsGuid((object)Sample.ToString()), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsGuid_Object_NonGuid_ReturnsFalse()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.IsGuid((object)12345), Is.False);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region FindFirstGuid / GetGuids
|
||||
|
||||
[Test]
|
||||
public void FindFirstGuid_EmbeddedGuid_ReturnsIt()
|
||||
{
|
||||
// Act
|
||||
var result = GuidUtils.FindFirstGuid($"prefix {Sample} suffix");
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(Sample));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FindFirstGuid_NoGuid_ReturnsEmpty()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.FindFirstGuid("nothing here"), Is.EqualTo(Guid.Empty));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetGuids_ReturnsAllEmbeddedGuids()
|
||||
{
|
||||
// Arrange
|
||||
var second = new Guid("99999999-9999-9999-9999-999999999999");
|
||||
|
||||
// Act
|
||||
var result = GuidUtils.GetGuids($"a {Sample} b {second} c");
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Has.Count.EqualTo(2));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetGuid
|
||||
|
||||
[Test]
|
||||
public void GetGuid_ValidString_ParsesValue()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.GetGuid(Sample.ToString()), Is.EqualTo(Sample));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetGuid_InvalidString_ReturnsEmpty()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.GetGuid("nope"), Is.EqualTo(Guid.Empty));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetGuid_InvalidString_ReturnsProvidedDefault()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.GetGuid("nope", Sample), Is.EqualTo(Sample));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetGuid_NullObject_ReturnsEmpty()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.GetGuid((object)null!), Is.EqualTo(Guid.Empty));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetGuid_Object_ParsesToStringValue()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(GuidUtils.GetGuid((object)Sample.ToString()), Is.EqualTo(Sample));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,480 @@
|
||||
using System.Data;
|
||||
using Strata.SqlTools.SqlBreakdown.Enums.SQL;
|
||||
using Strata.SqlTools.SqlBreakdown.Utilities;
|
||||
|
||||
namespace Strata.SqlTools.SqlBreakdown.Tests.Utilities;
|
||||
|
||||
[TestFixture]
|
||||
public class SqlUtilsTests
|
||||
{
|
||||
#region String Manipulation
|
||||
|
||||
[Test]
|
||||
public void StripColumnTableAlias_RemovesTableAliases()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.StripColumnTableAlias("a.Col1, b.Col2"), Is.EqualTo("Col1,Col2"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StripColumnTableAlias_NoAlias_LeavesColumnUntouched()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.StripColumnTableAlias("MyCol"), Is.EqualTo("MyCol"));
|
||||
}
|
||||
|
||||
[TestCase("O'Brien", "O''Brien")]
|
||||
[TestCase("", "")]
|
||||
[TestCase("clean", "clean")]
|
||||
public void EscapeInvalidCharacter_DoublesSingleQuotes(string input, string expected)
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.EscapeInvalidCharacter(input), Is.EqualTo(expected));
|
||||
}
|
||||
|
||||
[TestCase("Col", "[Col]")]
|
||||
[TestCase("[Col]", "[Col]")]
|
||||
[TestCase("[Col", "[Col]")]
|
||||
[TestCase("Col]", "[Col]")]
|
||||
public void AddBrackets_WrapsWhenMissing(string input, string expected)
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.AddBrackets(input), Is.EqualTo(expected));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveBrackets_StripsSquareBrackets()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.RemoveBrackets("[Col]"), Is.EqualTo("Col"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSqlFriendlyName_RemovesInvalidCharactersByDefault()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.GetSqlFriendlyName("a.b c"), Is.EqualTo("abc"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSqlFriendlyName_UsesReplacement()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.GetSqlFriendlyName("a.b c", "_"), Is.EqualTo("a_b_c"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Object Name Handling
|
||||
|
||||
[Test]
|
||||
public void GetSqlObjectExpression_BuildsBracketedExpression()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.GetSqlObjectExpression("dbo", "MyTable"), Is.EqualTo("[dbo].[MyTable]"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSqlObjectExpression_StripsExistingBrackets()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.GetSqlObjectExpression("[dbo]", "[MyTable]"), Is.EqualTo("[dbo].[MyTable]"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSqlObjectName_ExtractsObjectPortion()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.GetSqlObjectName("[dbo].[MyTable]"), Is.EqualTo("MyTable"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSqlObjectName_NoDot_ReturnsInput()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.GetSqlObjectName("MyTable"), Is.EqualTo("MyTable"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSqlObjectName_MultipleDots_Throws()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<NotSupportedException>(() => SqlUtils.GetSqlObjectName("a.b.c"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSqlSchemaName_ExtractsSchema()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.GetSqlSchemaName("data.DimClient"), Is.EqualTo("data"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSqlSchemaName_NoDot_ReturnsDbo()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.GetSqlSchemaName("DimClient"), Is.EqualTo("dbo"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSqlSchemaName_MultipleDots_Throws()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<NotSupportedException>(() => SqlUtils.GetSqlSchemaName("a.b.c"));
|
||||
}
|
||||
|
||||
[TestCase("dbo", true)]
|
||||
[TestCase("DBO", true)]
|
||||
[TestCase("data", false)]
|
||||
public void IsDefaultSchema_ChecksAgainstDbo(string schema, bool expected)
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.IsDefaultSchema(schema), Is.EqualTo(expected));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Data Type Conversions
|
||||
|
||||
[Test]
|
||||
public void GetStringConversionLength_KnownTypes()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.GetStringConversionLength(SqlDataType.Bit), Is.EqualTo(1));
|
||||
Assert.That(SqlUtils.GetStringConversionLength(SqlDataType.Int), Is.EqualTo(int.MaxValue.ToString().Length));
|
||||
Assert.That(SqlUtils.GetStringConversionLength(SqlDataType.UniqueIdentifier), Is.EqualTo(Guid.Empty.ToString().Length));
|
||||
Assert.That(SqlUtils.GetStringConversionLength(SqlDataType.NVarChar), Is.EqualTo(SqlUtils.MAX_NVARCHAR_LENGTH));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertGuidToAlias_ProducesPrefixedUppercaseAlias()
|
||||
{
|
||||
// Arrange
|
||||
var guid = new Guid("0123abcd-4567-89ef-0123-456789abcdef");
|
||||
|
||||
// Act
|
||||
var result = SqlUtils.ConvertGuidToAlias(guid, "p");
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(result, Does.StartWith("p"));
|
||||
Assert.That(result, Does.Not.Contain("-"));
|
||||
Assert.That(result, Is.EqualTo("p0123ABCD456789EF0123456789ABCDEF"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsFixedPrecision_DecimalIsNotFixed()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.IsFixedPrecision(SqlDataType.Decimal), Is.False);
|
||||
Assert.That(SqlUtils.IsFixedPrecision(SqlDataType.Int), Is.True);
|
||||
// IsFixedScale mirrors IsFixedPrecision
|
||||
Assert.That(SqlUtils.IsFixedScale(SqlDataType.Decimal), Is.False);
|
||||
Assert.That(SqlUtils.IsFixedScale(SqlDataType.Int), Is.True);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsFixedMaxLength_VariesByType()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.IsFixedMaxLength(SqlDataType.Int), Is.True);
|
||||
Assert.That(SqlUtils.IsFixedMaxLength(SqlDataType.UniqueIdentifier), Is.True);
|
||||
Assert.That(SqlUtils.IsFixedMaxLength(SqlDataType.VarChar), Is.False);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetFixedScale_KnownTypes()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.GetFixedScale(SqlDataType.DateTime), Is.EqualTo(3));
|
||||
Assert.That(SqlUtils.GetFixedScale(SqlDataType.Money), Is.EqualTo(4));
|
||||
Assert.That(SqlUtils.GetFixedScale(SqlDataType.Int), Is.EqualTo(0));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetFixedScale_Decimal_Throws()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<NotImplementedException>(() => SqlUtils.GetFixedScale(SqlDataType.Decimal));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetFixedPrecision_KnownTypes()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.GetFixedPrecision(SqlDataType.BigInt), Is.EqualTo(19));
|
||||
Assert.That(SqlUtils.GetFixedPrecision(SqlDataType.Int), Is.EqualTo(10));
|
||||
Assert.That(SqlUtils.GetFixedPrecision(SqlDataType.Bit), Is.EqualTo(1));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetFixedMaxLength_KnownTypes()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.GetFixedMaxLength(SqlDataType.Int), Is.EqualTo(4));
|
||||
Assert.That(SqlUtils.GetFixedMaxLength(SqlDataType.UniqueIdentifier), Is.EqualTo(16));
|
||||
Assert.That(SqlUtils.GetFixedMaxLength(SqlDataType.TinyInt), Is.EqualTo(1));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetFixedMaxLength_UnsupportedType_Throws()
|
||||
{
|
||||
// Act & Assert - VarChar has no fixed length
|
||||
Assert.Throws<NotImplementedException>(() => SqlUtils.GetFixedMaxLength(SqlDataType.VarChar));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Well-Known SQL Errors
|
||||
|
||||
[Test]
|
||||
public void GetWellKnownSqlError_DuplicateKeyRow_IsUniqueKeyViolation()
|
||||
{
|
||||
// Arrange
|
||||
var ex = new Exception("Cannot insert duplicate key row in object 'dbo.Users'.");
|
||||
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.GetWellKnownSqlError(ex), Is.EqualTo(SqlUtils.WellKnownSqlError.UniqueKeyViolation));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetWellKnownSqlError_ObjectAlreadyExists_IsDetected()
|
||||
{
|
||||
// Arrange
|
||||
var ex = new Exception("There is already an object named 'Users' in the database.");
|
||||
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.GetWellKnownSqlError(ex), Is.EqualTo(SqlUtils.WellKnownSqlError.ObjectAlreadyExists));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetWellKnownSqlError_TruncateForeignKey_IsDetected()
|
||||
{
|
||||
// Arrange
|
||||
var ex = new Exception("Cannot truncate table 'dbo.Orders' because it is being referenced by a FOREIGN KEY constraint.");
|
||||
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.GetWellKnownSqlError(ex), Is.EqualTo(SqlUtils.WellKnownSqlError.TruncateTableForeignKeyReferenceError));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetWellKnownSqlError_UnrecognizedMessage_IsUnknown()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.GetWellKnownSqlError(new Exception("Something else entirely")), Is.EqualTo(SqlUtils.WellKnownSqlError.Unknown));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Data Type Helpers
|
||||
|
||||
[Test]
|
||||
public void GetClientFriendlyDataTypeName_MapsCategories()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.GetClientFriendlyDataTypeName(SqlDataType.NVarChar), Is.EqualTo("Text"));
|
||||
Assert.That(SqlUtils.GetClientFriendlyDataTypeName(SqlDataType.Int), Is.EqualTo("Whole Number"));
|
||||
Assert.That(SqlUtils.GetClientFriendlyDataTypeName(SqlDataType.Decimal), Is.EqualTo("Decimal"));
|
||||
Assert.That(SqlUtils.GetClientFriendlyDataTypeName(SqlDataType.DateTime), Is.EqualTo("Date"));
|
||||
Assert.That(SqlUtils.GetClientFriendlyDataTypeName(SqlDataType.Money), Is.EqualTo("Dollars"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IdentityColumnTypes_ContainsIntegerTypes()
|
||||
{
|
||||
// Act
|
||||
var types = SqlUtils.IdentityColumnTypes().ToList();
|
||||
|
||||
// Assert
|
||||
Assert.That(types, Is.EquivalentTo(new[]
|
||||
{
|
||||
SqlDataType.BigInt, SqlDataType.TinyInt, SqlDataType.Int, SqlDataType.SmallInt
|
||||
}));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetOrderBySqlDirectionString_MapsDirections()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.GetOrderBySqlDirectionString(SortDirection.Ascending), Is.EqualTo("ASC"));
|
||||
Assert.That(SqlUtils.GetOrderBySqlDirectionString(SortDirection.Descending), Is.EqualTo("DESC"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSimpleDataType_MapsToCategories()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.GetSimpleDataType(SqlDataType.Int), Is.EqualTo(SimpleDataType.Numeric));
|
||||
Assert.That(SqlUtils.GetSimpleDataType(SqlDataType.DateTime), Is.EqualTo(SimpleDataType.Date));
|
||||
Assert.That(SqlUtils.GetSimpleDataType(SqlDataType.Bit), Is.EqualTo(SimpleDataType.Boolean));
|
||||
Assert.That(SqlUtils.GetSimpleDataType(SqlDataType.UniqueIdentifier), Is.EqualTo(SimpleDataType.GUID));
|
||||
Assert.That(SqlUtils.GetSimpleDataType(SqlDataType.NVarChar), Is.EqualTo(SimpleDataType.String));
|
||||
});
|
||||
}
|
||||
|
||||
[TestCase("1", true)]
|
||||
[TestCase("0", true)]
|
||||
[TestCase("yes", true)]
|
||||
[TestCase("no", true)]
|
||||
[TestCase("true", true)]
|
||||
[TestCase("maybe", false)]
|
||||
public void IsStringValueValidForSimpleDataType_Boolean(string value, bool expected)
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.IsStringValueValidForSimpleDataType(SimpleDataType.Boolean, value), Is.EqualTo(expected));
|
||||
}
|
||||
|
||||
[TestCase("3.14", true)]
|
||||
[TestCase("100", true)]
|
||||
[TestCase("abc", false)]
|
||||
public void IsStringValueValidForSimpleDataType_Numeric(string value, bool expected)
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.IsStringValueValidForSimpleDataType(SimpleDataType.Numeric, value), Is.EqualTo(expected));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsStringValueValidForSimpleDataType_GuidAndString()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.IsStringValueValidForSimpleDataType(SimpleDataType.GUID, Guid.NewGuid().ToString()), Is.True);
|
||||
Assert.That(SqlUtils.IsStringValueValidForSimpleDataType(SimpleDataType.GUID, "nope"), Is.False);
|
||||
// String accepts anything
|
||||
Assert.That(SqlUtils.IsStringValueValidForSimpleDataType(SimpleDataType.String, "anything"), Is.True);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetValueType_MapsToClrTypes()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.GetValueType(SqlDataType.Bit), Is.EqualTo(typeof(bool)));
|
||||
Assert.That(SqlUtils.GetValueType(SqlDataType.DateTime), Is.EqualTo(typeof(DateTime)));
|
||||
Assert.That(SqlUtils.GetValueType(SqlDataType.Int), Is.EqualTo(typeof(double)));
|
||||
Assert.That(SqlUtils.GetValueType(SqlDataType.UniqueIdentifier), Is.EqualTo(typeof(Guid)));
|
||||
Assert.That(SqlUtils.GetValueType(SqlDataType.NVarChar), Is.EqualTo(typeof(string)));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSqlDataType_MapsFromSqlDbType()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.GetSqlDataType(SqlDbType.Int), Is.EqualTo(SqlDataType.Int));
|
||||
Assert.That(SqlUtils.GetSqlDataType(SqlDbType.DateTime2), Is.EqualTo(SqlDataType.DateTime));
|
||||
Assert.That(SqlUtils.GetSqlDataType(SqlDbType.UniqueIdentifier), Is.EqualTo(SqlDataType.UniqueIdentifier));
|
||||
// Unmapped types fall back to NVarChar
|
||||
Assert.That(SqlUtils.GetSqlDataType(SqlDbType.Variant), Is.EqualTo(SqlDataType.NVarChar));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Default Values
|
||||
|
||||
[Test]
|
||||
public void GetSqlDefaultValueDefinition_KnownTypes()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.GetSqlDefaultValueDefinition(SqlDataType.Int), Is.EqualTo("(0)"));
|
||||
Assert.That(SqlUtils.GetSqlDefaultValueDefinition(SqlDataType.VarChar), Is.EqualTo("('')"));
|
||||
Assert.That(SqlUtils.GetSqlDefaultValueDefinition(SqlDataType.DateTime), Is.EqualTo("(getdate())"));
|
||||
Assert.That(SqlUtils.GetSqlDefaultValueDefinition(SqlDataType.UniqueIdentifier), Is.EqualTo($"('{Guid.Empty}')"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSqlZeroValue_KnownTypes()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.GetSqlZeroValue(SqlDataType.Int), Is.EqualTo(0));
|
||||
Assert.That(SqlUtils.GetSqlZeroValue(SqlDataType.NVarChar), Is.EqualTo(string.Empty));
|
||||
Assert.That(SqlUtils.GetSqlZeroValue(SqlDataType.DateTime), Is.EqualTo(new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Unspecified)));
|
||||
Assert.That(SqlUtils.GetSqlZeroValue(SqlDataType.UniqueIdentifier), Is.EqualTo(Guid.Empty));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSqlDefaultValue_NullDefinition_ReturnsNull()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.GetSqlDefaultValue(SqlDataType.Int, string.Empty), Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSqlDefaultValue_ParsesScalarTypes()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.GetSqlDefaultValue(SqlDataType.Int, "(0)"), Is.EqualTo(0));
|
||||
Assert.That(SqlUtils.GetSqlDefaultValue(SqlDataType.BigInt, "(123)"), Is.EqualTo(123L));
|
||||
Assert.That(SqlUtils.GetSqlDefaultValue(SqlDataType.Bit, "(1)"), Is.EqualTo(true));
|
||||
Assert.That(SqlUtils.GetSqlDefaultValue(SqlDataType.Bit, "(0)"), Is.EqualTo(false));
|
||||
Assert.That(SqlUtils.GetSqlDefaultValue(SqlDataType.NVarChar, "('hello')"), Is.EqualTo("hello"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSqlDefaultValue_UniqueIdentifierZeroGuid_ReturnsEmpty()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(SqlUtils.GetSqlDefaultValue(SqlDataType.UniqueIdentifier, "(dbo.ZeroGUID())"), Is.EqualTo(Guid.Empty));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Join / Connection Strings
|
||||
|
||||
[Test]
|
||||
public void GetSqlJoinTypeString_MapsJoinTypes()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(SqlUtils.GetSqlJoinTypeString(SqlJoinType.Left), Is.EqualTo("LEFT"));
|
||||
Assert.That(SqlUtils.GetSqlJoinTypeString(SqlJoinType.Right), Is.EqualTo("RIGHT"));
|
||||
Assert.That(SqlUtils.GetSqlJoinTypeString(SqlJoinType.Inner), Is.EqualTo("INNER"));
|
||||
Assert.That(SqlUtils.GetSqlJoinTypeString(SqlJoinType.Cross), Is.EqualTo("CROSS"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSqlConnectionString_BuildsIntegratedSecurityConnection()
|
||||
{
|
||||
// Act
|
||||
var result = SqlUtils.GetSqlConnectionString("MyServer", "MyDb");
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(result, Does.Contain("data source=MyServer;"));
|
||||
Assert.That(result, Does.Contain("initial catalog=MyDb;"));
|
||||
Assert.That(result, Does.Contain("Integrated Security=SSPI;"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Strata.SqlTools.SqlBreakdown.Utilities;
|
||||
|
||||
namespace Strata.SqlTools.SqlBreakdown.Tests.Utilities;
|
||||
|
||||
[TestFixture]
|
||||
public class StringUtilsTests
|
||||
{
|
||||
[TestCase('a', -842352705)]
|
||||
[TestCase('z', -842352730)]
|
||||
[TestCase('A', -842352673)]
|
||||
[TestCase('Z', -842352698)]
|
||||
[TestCase('0', -842352768)]
|
||||
[TestCase('9', -842352759)]
|
||||
[TestCase(' ', -842352737)]
|
||||
[TestCase('-', -842352782)]
|
||||
public void GetHashCode32Bit_KnownCharacters_ReturnsHardcodedHash(char c, int expected)
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.That(StringUtils.GetHashCode32Bit(c), Is.EqualTo(expected));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetHashCode32Bit_UnmappedCharacter_UsesConsistentFallback()
|
||||
{
|
||||
// Arrange - '!' is not in the hardcoded table
|
||||
const char c = '!';
|
||||
var expected = -842352737 - (int)c;
|
||||
|
||||
// Act & Assert
|
||||
Assert.That(StringUtils.GetHashCode32Bit(c), Is.EqualTo(expected));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetHashCode32Bit_SameCharacter_IsDeterministic()
|
||||
{
|
||||
// Act & Assert - critical: TranslateTextToGuid relies on stable hashing
|
||||
Assert.That(StringUtils.GetHashCode32Bit('q'), Is.EqualTo(StringUtils.GetHashCode32Bit('q')));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
using Strata.SqlTools.Breakdowns.SqlServer;
|
||||
|
||||
namespace Strata.SqlTools.SqlBreakdown.Tests.SqlServer;
|
||||
|
||||
[TestFixture]
|
||||
public class DeleteBreakdownTests
|
||||
{
|
||||
#region Constructor Tests
|
||||
|
||||
[Test]
|
||||
public void Constructor_Default_InitializesEmptyClauses()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new DeleteBreakdown();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.FromClause.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.WhereClause.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.DeleteClause.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.IsUsingWhereClause, Is.False);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Constructor_WithClauses_SetsProperties()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new DeleteBreakdown("Users", "Id = @Id");
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.FromClause.Clause, Is.EqualTo("Users"));
|
||||
Assert.That(breakdown.WhereClause.Clause, Is.EqualTo("Id = @Id"));
|
||||
Assert.That(breakdown.IsUsingWhereClause, Is.True);
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetSql Tests
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithWhere_RendersDeleteFromWhere()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new DeleteBreakdown("Users", "Id = @Id");
|
||||
|
||||
// Act
|
||||
var sql = breakdown.GetSql();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(sql, Does.Contain("DELETE"));
|
||||
Assert.That(sql, Does.Contain("FROM"));
|
||||
Assert.That(sql, Does.Contain("Users"));
|
||||
Assert.That(sql, Does.Contain("WHERE"));
|
||||
Assert.That(sql, Does.Contain("Id = @Id"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithoutWhere_OmitsWhereKeyword()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new DeleteBreakdown("Users", string.Empty);
|
||||
|
||||
// Act
|
||||
var sql = breakdown.GetSql();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(sql, Does.Contain("DELETE"));
|
||||
Assert.That(sql, Does.Not.Contain("WHERE"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithDeleteClause_RendersAlias()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new DeleteBreakdown("Users u", "u.Id = 1")
|
||||
{
|
||||
DeleteClause = { Clause = "u" }
|
||||
};
|
||||
|
||||
// Act
|
||||
var sql = breakdown.GetSql();
|
||||
|
||||
// Assert
|
||||
Assert.That(sql, Does.Contain("DELETE"));
|
||||
Assert.That(sql, Does.Contain("u"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Parse Tests
|
||||
|
||||
[Test]
|
||||
public void Parse_SimpleDeleteFrom_PopulatesClauses()
|
||||
{
|
||||
// Arrange
|
||||
var input = "DELETE FROM Users WHERE Id = 1";
|
||||
|
||||
// Act
|
||||
var breakdown = DeleteBreakdown.Parse(input);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.FromClause.Clause, Is.EqualTo("Users"));
|
||||
Assert.That(breakdown.WhereClause.Clause, Is.EqualTo("Id = 1"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_DeleteWithAlias_PopulatesDeleteAndFromClauses()
|
||||
{
|
||||
// Arrange - DELETE u FROM Users u WHERE ... uses the alias pattern
|
||||
var input = "DELETE u FROM Users u WHERE u.Id = 1";
|
||||
|
||||
// Act
|
||||
var breakdown = DeleteBreakdown.Parse(input);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.DeleteClause.Clause, Is.EqualTo("u"));
|
||||
Assert.That(breakdown.FromClause.Clause, Is.EqualTo("Users u"));
|
||||
Assert.That(breakdown.WhereClause.Clause, Is.EqualTo("u.Id = 1"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_DeleteWithoutWhere_LeavesWhereEmpty()
|
||||
{
|
||||
// Arrange
|
||||
var input = "DELETE FROM Users";
|
||||
|
||||
// Act
|
||||
var breakdown = DeleteBreakdown.Parse(input);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.FromClause.Clause, Is.EqualTo("Users"));
|
||||
Assert.That(breakdown.IsUsingWhereClause, Is.False);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NullOrWhitespace_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => DeleteBreakdown.Parse(null!));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NotADeleteStatement_ThrowsFormatException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<FormatException>(() => DeleteBreakdown.Parse("SELECT * FROM Users"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_WrongPrefix_ReturnsFalseWithMessage()
|
||||
{
|
||||
// Act
|
||||
var success = DeleteBreakdown.TryParse("UPDATE Users SET Id = 1", out _, out var error);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.False);
|
||||
Assert.That(error, Does.Contain("DELETE"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_ValidDelete_ReturnsTrue()
|
||||
{
|
||||
// Act
|
||||
var success = DeleteBreakdown.TryParse("DELETE FROM Users WHERE Id = 1", out var breakdown);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.True);
|
||||
Assert.That(breakdown.FromClause.Clause, Is.EqualTo("Users"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
using Strata.SqlTools.Breakdowns.SqlServer;
|
||||
|
||||
namespace Strata.SqlTools.SqlBreakdown.Tests.SqlServer;
|
||||
|
||||
[TestFixture]
|
||||
public class InsertBreakdownTests
|
||||
{
|
||||
#region Constructor Tests
|
||||
|
||||
[Test]
|
||||
public void Constructor_Default_InitializesEmptyClauses()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new InsertBreakdown();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.InsertIntoClause.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.ValuesClause.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.SetupClauses, Is.Empty);
|
||||
Assert.That(breakdown.FinishClauses, Is.Empty);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Constructor_WithClauses_SetsProperties()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new InsertBreakdown("Users", "Id, Name", "@Id, @Name");
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("Users"));
|
||||
Assert.That(breakdown.InsertIntoClause.Clause, Is.EqualTo("Id, Name"));
|
||||
Assert.That(breakdown.ValuesClause.Clause, Is.EqualTo("@Id, @Name"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Constructor_WithClauses_ExtractsComments()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new InsertBreakdown("Users /* target */", "Id, Name", "@Id, @Name");
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("Users"));
|
||||
Assert.That(breakdown.TableName.Comment, Does.Contain("target"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Constructor_WithColumnNames_GeneratesBracketedColumnsAndAtParameters()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new InsertBreakdown("Users", new List<string> { "Id", "Name" });
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("Users"));
|
||||
Assert.That(breakdown.InsertIntoClause.Clause, Is.EqualTo("[Id],[Name]"));
|
||||
Assert.That(breakdown.ValuesClause.Clause, Is.EqualTo("@Id,@Name"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetSql Tests
|
||||
|
||||
[Test]
|
||||
public void GetSql_RendersInsertIntoTableColumnsValues()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new InsertBreakdown("Users", "Id, Name", "@Id, @Name");
|
||||
|
||||
// Act
|
||||
var sql = breakdown.GetSql();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(sql, Does.Contain("INSERT INTO"));
|
||||
Assert.That(sql, Does.Contain("Users"));
|
||||
Assert.That(sql, Does.Contain("Id, Name"));
|
||||
Assert.That(sql, Does.Contain("VALUES"));
|
||||
Assert.That(sql, Does.Contain("@Id, @Name"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToString_ReturnsGeneratedSql()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new InsertBreakdown("Users", "Id", "@Id");
|
||||
|
||||
// Act & Assert
|
||||
Assert.That(breakdown.ToString(), Does.Contain("INSERT INTO"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Parse Tests
|
||||
|
||||
[Test]
|
||||
public void Parse_ValidInsert_PopulatesClauses()
|
||||
{
|
||||
// Arrange
|
||||
var input = "INSERT INTO Users (Id, Name) VALUES (1, 'Bob')";
|
||||
|
||||
// Act
|
||||
var breakdown = InsertBreakdown.Parse(input);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("Users"));
|
||||
Assert.That(breakdown.InsertIntoClause.Clause, Is.EqualTo("Id, Name"));
|
||||
Assert.That(breakdown.ValuesClause.Clause, Is.EqualTo("1, 'Bob'"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NullOrWhitespace_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => InsertBreakdown.Parse(" "));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NotAnInsertStatement_ThrowsFormatException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<FormatException>(() => InsertBreakdown.Parse("SELECT * FROM Users"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_ValidInsert_ReturnsTrue()
|
||||
{
|
||||
// Act
|
||||
var success = InsertBreakdown.TryParse("INSERT INTO Users (Id) VALUES (1)", out var breakdown);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.True);
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("Users"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_WrongPrefix_ReturnsFalseWithMessage()
|
||||
{
|
||||
// Act
|
||||
var success = InsertBreakdown.TryParse("UPDATE Users SET Id = 1", out _, out var error);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.False);
|
||||
Assert.That(error, Does.Contain("INSERT INTO"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_MalformedInsert_ReturnsFalse()
|
||||
{
|
||||
// Act - matches the INSERT INTO prefix but not the column/values grammar
|
||||
var success = InsertBreakdown.TryParse("INSERT INTO Users", out _, out var error);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.False);
|
||||
Assert.That(error, Is.Not.Null.And.Not.Empty);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSql_IncludeSetupFinish_RendersSetupAndFinishClauses()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new InsertBreakdown("Users", "Id", "@Id")
|
||||
{
|
||||
SetupClauses = { "SET NOCOUNT ON" },
|
||||
FinishClauses = { "SELECT SCOPE_IDENTITY()" }
|
||||
};
|
||||
|
||||
// Act
|
||||
var withClauses = breakdown.GetSql(includeSetupFinish: true);
|
||||
var withoutClauses = breakdown.GetSql(includeSetupFinish: false);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(withClauses, Does.Contain("SET NOCOUNT ON"));
|
||||
Assert.That(withClauses, Does.Contain("SELECT SCOPE_IDENTITY()"));
|
||||
Assert.That(withClauses, Does.Contain("INSERT INTO"));
|
||||
Assert.That(withoutClauses, Does.Not.Contain("SET NOCOUNT ON"));
|
||||
Assert.That(withoutClauses, Does.Not.Contain("SELECT SCOPE_IDENTITY()"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
using Strata.SqlTools.Breakdowns.SqlServer;
|
||||
|
||||
namespace Strata.SqlTools.SqlBreakdown.Tests.SqlServer;
|
||||
|
||||
[TestFixture]
|
||||
public class ProcedureBreakdownTests
|
||||
{
|
||||
#region Constructor Tests
|
||||
|
||||
[Test]
|
||||
public void Constructor_Default_InitializesEmptyState()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new ProcedureBreakdown();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.ProcedureName.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.Parameters, Is.Empty);
|
||||
Assert.That(breakdown.IsUsingParameters, Is.False);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Constructor_WithName_SetsProcedureName()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new ProcedureBreakdown("dbo.GetUsers");
|
||||
|
||||
// Assert
|
||||
Assert.That(breakdown.ProcedureName.Clause, Is.EqualTo("dbo.GetUsers"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Constructor_WithParameters_SetsParameters()
|
||||
{
|
||||
// Arrange
|
||||
var parameters = new Dictionary<string, string> { ["@Id"] = "1" };
|
||||
|
||||
// Act
|
||||
var breakdown = new ProcedureBreakdown("dbo.GetUser", parameters);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.IsUsingParameters, Is.True);
|
||||
Assert.That(breakdown.Parameters["@Id"], Is.EqualTo("1"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AddParameter Tests
|
||||
|
||||
[Test]
|
||||
public void AddParameter_WithoutAtPrefix_AddsAtPrefix()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new ProcedureBreakdown("dbo.GetUser");
|
||||
|
||||
// Act
|
||||
breakdown.AddParameter("Id", "1");
|
||||
|
||||
// Assert
|
||||
Assert.That(breakdown.Parameters.ContainsKey("@Id"), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddParameter_WithAtPrefix_KeepsSinglePrefix()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new ProcedureBreakdown("dbo.GetUser");
|
||||
|
||||
// Act
|
||||
breakdown.AddParameter("@Id", "1");
|
||||
|
||||
// Assert
|
||||
Assert.That(breakdown.Parameters.ContainsKey("@Id"), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddParameter_NullName_ThrowsArgumentNullException()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new ProcedureBreakdown("dbo.GetUser");
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => breakdown.AddParameter(" ", "1"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetSql Tests
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithoutParameters_RendersExecName()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new ProcedureBreakdown("dbo.GetUsers");
|
||||
|
||||
// Act
|
||||
var sql = breakdown.GetSql();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(sql, Does.Contain("EXEC"));
|
||||
Assert.That(sql, Does.Contain("dbo.GetUsers"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithParameters_RendersNamedAssignments()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new ProcedureBreakdown("dbo.GetUser");
|
||||
breakdown.AddParameter("@Id", "1");
|
||||
|
||||
// Act
|
||||
var sql = breakdown.GetSql();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(sql, Does.Contain("EXEC"));
|
||||
Assert.That(sql, Does.Contain("@Id = 1"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Parse Tests
|
||||
|
||||
[Test]
|
||||
public void Parse_ExecWithoutParameters_PopulatesName()
|
||||
{
|
||||
// Arrange
|
||||
var input = "EXEC dbo.GetUsers";
|
||||
|
||||
// Act
|
||||
var breakdown = ProcedureBreakdown.Parse(input);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.ProcedureName.Clause, Is.EqualTo("dbo.GetUsers"));
|
||||
Assert.That(breakdown.IsUsingParameters, Is.False);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_ExecWithParameters_PopulatesParameters()
|
||||
{
|
||||
// Arrange
|
||||
var input = "EXEC dbo.GetUser @Id = 1, @Active = 1";
|
||||
|
||||
// Act
|
||||
var breakdown = ProcedureBreakdown.Parse(input);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.ProcedureName.Clause, Is.EqualTo("dbo.GetUser"));
|
||||
Assert.That(breakdown.Parameters["@Id"], Is.EqualTo("1"));
|
||||
Assert.That(breakdown.Parameters["@Active"], Is.EqualTo("1"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_ExecuteKeyword_IsAccepted()
|
||||
{
|
||||
// Act
|
||||
var breakdown = ProcedureBreakdown.Parse("EXECUTE dbo.GetUsers");
|
||||
|
||||
// Assert
|
||||
Assert.That(breakdown.ProcedureName.Clause, Is.EqualTo("dbo.GetUsers"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NullOrWhitespace_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => ProcedureBreakdown.Parse(" "));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NotAnExecStatement_ThrowsFormatException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<FormatException>(() => ProcedureBreakdown.Parse("SELECT * FROM Users"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_WrongPrefix_ReturnsFalseWithMessage()
|
||||
{
|
||||
// Act
|
||||
var success = ProcedureBreakdown.TryParse("SELECT 1", out _, out var error);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.False);
|
||||
Assert.That(error, Does.Contain("EXEC"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_ValidExec_ReturnsTrue()
|
||||
{
|
||||
// Act
|
||||
var success = ProcedureBreakdown.TryParse("EXEC dbo.GetUsers", out var breakdown);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.True);
|
||||
Assert.That(breakdown.ProcedureName.Clause, Is.EqualTo("dbo.GetUsers"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
using Strata.SqlTools.Breakdowns.SqlServer;
|
||||
|
||||
namespace Strata.SqlTools.SqlBreakdown.Tests.SqlServer;
|
||||
|
||||
[TestFixture]
|
||||
public class UpdateBreakdownTests
|
||||
{
|
||||
#region Constructor Tests
|
||||
|
||||
[Test]
|
||||
public void Constructor_Default_InitializesEmptyClauses()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new UpdateBreakdown();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.SetClause.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.FromClause.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.WhereClause.Clause, Is.EqualTo(string.Empty));
|
||||
Assert.That(breakdown.IsUsingFromClause, Is.False);
|
||||
Assert.That(breakdown.IsUsingWhereClause, Is.False);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Constructor_WithClauses_SetsProperties()
|
||||
{
|
||||
// Arrange & Act
|
||||
var breakdown = new UpdateBreakdown("Users", "Name = @Name", "Id = @Id");
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("Users"));
|
||||
Assert.That(breakdown.SetClause.Clause, Is.EqualTo("Name = @Name"));
|
||||
Assert.That(breakdown.WhereClause.Clause, Is.EqualTo("Id = @Id"));
|
||||
Assert.That(breakdown.IsUsingWhereClause, Is.True);
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetSql Tests
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithWhere_RendersUpdateSetWhere()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new UpdateBreakdown("Users", "Name = @Name", "Id = @Id");
|
||||
|
||||
// Act
|
||||
var sql = breakdown.GetSql();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(sql, Does.Contain("UPDATE"));
|
||||
Assert.That(sql, Does.Contain("Users"));
|
||||
Assert.That(sql, Does.Contain("SET"));
|
||||
Assert.That(sql, Does.Contain("Name = @Name"));
|
||||
Assert.That(sql, Does.Contain("WHERE"));
|
||||
Assert.That(sql, Does.Contain("Id = @Id"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithoutWhere_OmitsWhereKeyword()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new UpdateBreakdown("Users", "Name = @Name", string.Empty);
|
||||
|
||||
// Act
|
||||
var sql = breakdown.GetSql();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(sql, Does.Contain("UPDATE"));
|
||||
Assert.That(sql, Does.Not.Contain("WHERE"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithFromClause_RendersFromSection()
|
||||
{
|
||||
// Arrange
|
||||
var breakdown = new UpdateBreakdown("u", "u.Name = s.Name", "u.Id = s.Id")
|
||||
{
|
||||
FromClause = { Clause = "Users u INNER JOIN Staging s ON u.Id = s.Id" }
|
||||
};
|
||||
|
||||
// Act
|
||||
var sql = breakdown.GetSql();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.IsUsingFromClause, Is.True);
|
||||
Assert.That(sql, Does.Contain("FROM"));
|
||||
Assert.That(sql, Does.Contain("INNER JOIN Staging"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Parse Tests
|
||||
|
||||
[Test]
|
||||
public void Parse_SimpleUpdate_PopulatesClauses()
|
||||
{
|
||||
// Arrange
|
||||
var input = "UPDATE Users SET Name = 'Bob' WHERE Id = 1";
|
||||
|
||||
// Act
|
||||
var breakdown = UpdateBreakdown.Parse(input);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("Users"));
|
||||
Assert.That(breakdown.SetClause.Clause, Is.EqualTo("Name = 'Bob'"));
|
||||
Assert.That(breakdown.WhereClause.Clause, Is.EqualTo("Id = 1"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_UpdateWithFrom_PopulatesFromClause()
|
||||
{
|
||||
// Arrange
|
||||
var input = "UPDATE u SET u.Name = s.Name FROM Users u INNER JOIN Staging s ON u.Id = s.Id WHERE s.Active = 1";
|
||||
|
||||
// Act
|
||||
var breakdown = UpdateBreakdown.Parse(input);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("u"));
|
||||
Assert.That(breakdown.IsUsingFromClause, Is.True);
|
||||
Assert.That(breakdown.FromClause.Clause, Does.Contain("INNER JOIN Staging"));
|
||||
Assert.That(breakdown.WhereClause.Clause, Is.EqualTo("s.Active = 1"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_UpdateWithoutWhere_LeavesWhereEmpty()
|
||||
{
|
||||
// Arrange
|
||||
var input = "UPDATE Users SET Name = 'Bob'";
|
||||
|
||||
// Act
|
||||
var breakdown = UpdateBreakdown.Parse(input);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(breakdown.SetClause.Clause, Is.EqualTo("Name = 'Bob'"));
|
||||
Assert.That(breakdown.IsUsingWhereClause, Is.False);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NullOrWhitespace_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => UpdateBreakdown.Parse(string.Empty));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NotAnUpdateStatement_ThrowsFormatException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<FormatException>(() => UpdateBreakdown.Parse("DELETE FROM Users"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_WrongPrefix_ReturnsFalseWithMessage()
|
||||
{
|
||||
// Act
|
||||
var success = UpdateBreakdown.TryParse("SELECT * FROM Users", out _, out var error);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.False);
|
||||
Assert.That(error, Does.Contain("UPDATE"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_ValidUpdate_ReturnsTrue()
|
||||
{
|
||||
// Act
|
||||
var success = UpdateBreakdown.TryParse("UPDATE Users SET Name = 'Bob' WHERE Id = 1", out var breakdown);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert
|
||||
Assert.That(success, Is.True);
|
||||
Assert.That(breakdown.TableName.Clause, Is.EqualTo("Users"));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user