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,285 @@
using Strata.SqlTools.Breakdowns.SqlServer;
using Strata.SqlTools.Markdown.SqlServer;
namespace Strata.SqlTools.Markdown.Tests.SqlServer;
[TestFixture]
public class QueryBreakdownCollectionGeneratorTests
{
private QueryBreakdownCollection _collection = null!;
[SetUp]
public void Setup()
{
_collection = new QueryBreakdownCollection();
}
[Test]
public void GenerateCollectionReport_WithTitle_IncludesTitle()
{
// Arrange
_collection.Add(new QueryBreakdown("ID, Name", "Users"));
var title = "User Query Report";
// Act
var report = QueryBreakdownCollectionGenerator.GenerateCollectionReport(_collection, title);
// Assert
Assert.That(report, Does.Contain(title));
Assert.That(report, Does.Contain("# User Query Report"));
}
[Test]
public void GenerateCollectionReport_WithMultipleQueries_GeneratesCompleteReport()
{
// Arrange
_collection.Add(new QueryBreakdown("ID, Name, Email", "Users"));
_collection.Add(new QueryBreakdown("OrderID, Amount", "Orders"));
// Act
var report = QueryBreakdownCollectionGenerator.GenerateCollectionReport(_collection);
// Assert
Assert.That(report, Does.Contain("Collection Summary"));
Assert.That(report, Does.Contain("Parameter Analysis"));
Assert.That(report, Does.Contain("Query Composition Report"));
Assert.That(report, Does.Contain("Total Queries"));
}
[Test]
public void GenerateCollectionSummary_WithQueries_IncludesSummaryMetrics()
{
// Arrange
_collection.Add(new QueryBreakdown("ID, Name, Email", "Users"));
_collection.Add(new QueryBreakdown("OrderID, Amount", "Orders"));
// Act
var summary = QueryBreakdownCollectionGenerator.GenerateCollectionSummary(_collection);
// Assert
Assert.That(summary, Does.Contain("Collection Summary"));
Assert.That(summary, Does.Contain("Total Queries"));
Assert.That(summary, Does.Contain("2"));
Assert.That(summary, Does.Contain("Unique Tables"));
}
[Test]
public void GenerateParameterAnalysis_NoParameters_IndicatesNoParameters()
{
// Arrange
_collection.Add(new QueryBreakdown("ID, Name", "Users"));
// Act
var analysis = QueryBreakdownCollectionGenerator.GenerateParameterAnalysis(_collection);
// Assert
Assert.That(analysis, Does.Contain("Parameters"));
Assert.That(analysis, Does.Contain("No parameters"));
}
[Test]
public void GenerateParameterAnalysis_WithParameters_IncludesParameterTable()
{
// Arrange
var query = new QueryBreakdown("ID, Name", "Users", "ID = @UserId");
query.Parameters["UserId"] = 123;
_collection.Add(query);
// Act
var analysis = QueryBreakdownCollectionGenerator.GenerateParameterAnalysis(_collection);
// Assert
Assert.That(analysis, Does.Contain("Parameter Analysis"));
Assert.That(analysis, Does.Contain("@UserId"));
Assert.That(analysis, Does.Contain("Parameter Dependency Diagram"));
Assert.That(analysis, Does.Contain("```mermaid"));
}
[Test]
public void GenerateParameterDependencyDiagram_WithParameters_GeneratesMermaidDiagram()
{
// Arrange
var query1 = new QueryBreakdown("ID, Name", "Users", "ID = @UserId");
var query2 = new QueryBreakdown("OrderID", "Orders", "UserID = @UserId");
query1.Parameters["UserId"] = 123;
query2.Parameters["UserId"] = 123;
_collection.Add(query1);
_collection.Add(query2);
// Act
var diagram = QueryBreakdownCollectionGenerator.GenerateParameterDependencyDiagram(_collection);
// Assert
Assert.That(diagram, Does.Contain("```mermaid"));
Assert.That(diagram, Does.Contain("graph TD"));
Assert.That(diagram, Does.Contain("@UserId"));
Assert.That(diagram, Does.Contain("Query #0"));
Assert.That(diagram, Does.Contain("Query #1"));
Assert.That(diagram, Does.Contain("```"));
}
[Test]
public void GenerateQueryCompositionReport_WithQueries_IncludesAllQueryDetails()
{
// Arrange
var query = new QueryBreakdown("ID, Name", "Users", "ID > 10");
query.GroupByClause.Clause = "Region";
query.OrderByClause.Clause = "Name ASC";
_collection.Add(query);
// Act
var report = QueryBreakdownCollectionGenerator.GenerateQueryCompositionReport(_collection);
// Assert
Assert.That(report, Does.Contain("Query Composition Report"));
Assert.That(report, Does.Contain("Query #0"));
Assert.That(report, Does.Contain("SELECT Clause"));
Assert.That(report, Does.Contain("✓ Yes"));
Assert.That(report, Does.Contain("WHERE Clause"));
Assert.That(report, Does.Contain("GROUP BY"));
Assert.That(report, Does.Contain("ORDER BY"));
}
[Test]
public void GenerateQueryCompositionReport_WithCTEs_IncludesCTEList()
{
// Arrange
var query = new QueryBreakdown("ID, Name", "Users");
var cteQuery = new QueryBreakdown("ID, Name", "ArchiveUsers");
query.AddWithClause("ActiveUsers", cteQuery);
_collection.Add(query);
// Act
var report = QueryBreakdownCollectionGenerator.GenerateQueryCompositionReport(_collection);
// Assert
Assert.That(report, Does.Contain("CTEs Defined"));
Assert.That(report, Does.Contain("ActiveUsers"));
}
[Test]
public void GenerateQueryCompositionReport_WithParameters_IncludesParameterValues()
{
// Arrange
var query = new QueryBreakdown("ID, Name", "Users", "ID = @UserId AND Status = @Status");
query.Parameters["UserId"] = 123;
query.Parameters["Status"] = "Active";
_collection.Add(query);
// Act
var report = QueryBreakdownCollectionGenerator.GenerateQueryCompositionReport(_collection);
// Assert
Assert.That(report, Does.Contain("Parameters Used"));
Assert.That(report, Does.Contain("@UserId"));
Assert.That(report, Does.Contain("@Status"));
Assert.That(report, Does.Contain("123"));
Assert.That(report, Does.Contain("Active"));
}
[Test]
public void GenerateBatchFlowDiagram_WithQueries_GeneratesFlowDiagram()
{
// Arrange
_collection.Add(new QueryBreakdown("ID, Name", "Users"));
_collection.Add(new QueryBreakdown("OrderID", "Orders"));
// Act
var diagram = QueryBreakdownCollectionGenerator.GenerateBatchFlowDiagram(_collection);
// Assert
Assert.That(diagram, Does.Contain("```mermaid"));
Assert.That(diagram, Does.Contain("flowchart TD"));
Assert.That(diagram, Does.Contain("Batch Start"));
Assert.That(diagram, Does.Contain("Query 0"));
Assert.That(diagram, Does.Contain("Query 1"));
Assert.That(diagram, Does.Contain("Batch Complete"));
Assert.That(diagram, Does.Contain("```"));
}
[Test]
public void GenerateBatchFlowDiagram_WithTransaction_IncludesTransactionStatements()
{
// Arrange
_collection.Add(new QueryBreakdown("ID, Name", "Users"));
// Act
var diagram = QueryBreakdownCollectionGenerator.GenerateBatchFlowDiagram(_collection, includeTransaction: true);
// Assert
Assert.That(diagram, Does.Contain("BEGIN TRANSACTION"));
Assert.That(diagram, Does.Contain("COMMIT TRANSACTION"));
}
[Test]
public void GenerateBatchFlowDiagram_WithQueries_ValidatesProperConnections()
{
// Arrange
_collection.Add(new QueryBreakdown("ID, Name", "Users"));
_collection.Add(new QueryBreakdown("OrderID", "Orders"));
_collection.Add(new QueryBreakdown("ProductID", "Products"));
// Act
var diagram = QueryBreakdownCollectionGenerator.GenerateBatchFlowDiagram(_collection);
// Assert
// Verify proper connections between nodes
Assert.That(diagram, Does.Contain("Start([Batch Start]) --> node0")); // Start connects to first node
Assert.That(diagram, Does.Contain("node0[\"Query 0\"] --> node1")); // Query 0 to Query 1
Assert.That(diagram, Does.Contain("node1[\"Query 1\"] --> node2")); // Query 1 to Query 2
Assert.That(diagram, Does.Contain("node2[\"Query 2\"] --> End")); // Last query connects to End
// Verify no dangling nodes
Assert.That(diagram, Does.Not.Contain("node3")); // No extra unconnected node
}
[Test]
public void GenerateBatchFlowDiagram_WithTransaction_ValidatesProperConnections()
{
// Arrange
_collection.Add(new QueryBreakdown("ID, Name", "Users"));
_collection.Add(new QueryBreakdown("OrderID", "Orders"));
// Act
var diagram = QueryBreakdownCollectionGenerator.GenerateBatchFlowDiagram(_collection, includeTransaction: true);
// Assert
// Verify proper transaction flow
Assert.That(diagram, Does.Contain("Start([Batch Start]) --> node0")); // Start connects to BEGIN TRANSACTION
Assert.That(diagram, Does.Contain("node0[\"BEGIN TRANSACTION\"]")); // BEGIN TRANSACTION node
Assert.That(diagram, Does.Contain("node0 --> node1")); // BEGIN to first query
Assert.That(diagram, Does.Contain("node1[\"Query 0\"] --> node2")); // Query 0 to Query 1
Assert.That(diagram, Does.Contain("node2[\"Query 1\"] --> node3")); // Query 1 to COMMIT
Assert.That(diagram, Does.Contain("node3[\"COMMIT TRANSACTION\"]")); // COMMIT node
Assert.That(diagram, Does.Contain("node3 --> End")); // COMMIT to End
}
[Test]
public void GenerateCollectionReport_EmptyCollection_GeneratesValidMarkdown()
{
// Act
var report = QueryBreakdownCollectionGenerator.GenerateCollectionReport(_collection);
// Assert
Assert.That(report, Does.Contain("Collection Summary"));
Assert.That(report, Does.Contain("Total Queries"));
Assert.That(report, Does.Contain("0"));
}
[Test]
public void GenerateCollectionReport_MultipleQueries_ContainsAllSections()
{
// Arrange
for (int i = 0; i < 3; i++)
{
_collection.Add(new QueryBreakdown($"Col{i}", $"Table{i}"));
}
// Act
var report = QueryBreakdownCollectionGenerator.GenerateCollectionReport(_collection);
// Assert
Assert.That(report, Does.Contain("## Collection Summary"));
Assert.That(report, Does.Contain("## Parameter Analysis"));
Assert.That(report, Does.Contain("## Query Composition Report"));
}
}
@@ -0,0 +1,154 @@
using Strata.SqlTools.Breakdowns.SqlServer;
using Strata.SqlTools.Markdown.SqlServer;
using Interfaces = Strata.SqlTools.SqlBreakdown.Interfaces;
namespace Strata.SqlTools.Markdown.Tests.SqlServer;
[TestFixture]
public class QueryBreakdownGeneratorTests
{
private QueryBreakdownGenerator _generator = null!;
[SetUp]
public void Setup()
{
_generator = new QueryBreakdownGenerator();
}
[Test]
public void GenerateMermaidDiagram_WithSimpleQuery_GeneratesFlowchart()
{
// Arrange
var query = new QueryBreakdown("ID, Name", "Users");
// Act
var result = _generator.GenerateMermaidDiagram(query);
// Assert
Assert.That(result, Does.Contain("```mermaid"));
Assert.That(result, Does.Contain("flowchart TD"));
Assert.That(result, Does.Contain("SELECT"));
Assert.That(result, Does.Contain("FROM"));
Assert.That(result, Does.Contain("```"));
}
[Test]
public void GenerateMermaidDiagram_WithComplexQuery_IncludesAllClauses()
{
// Arrange
var query = new QueryBreakdown(
"u.ID, u.Name, COUNT(o.OrderID) as OrderCount",
"Users u JOIN Orders o ON u.ID = o.UserID",
"u.Active = 1"
);
query.GroupByClause.Clause = "u.ID, u.Name";
query.HavingClause.Clause = "COUNT(o.OrderID) > 5";
query.OrderByClause.Clause = "OrderCount DESC";
// Act
var result = _generator.GenerateMermaidDiagram(query, "User Orders Query");
// Assert
Assert.That(result, Does.Contain("### User Orders Query"));
Assert.That(result, Does.Contain("SELECT"));
Assert.That(result, Does.Contain("FROM"));
Assert.That(result, Does.Contain("WHERE"));
Assert.That(result, Does.Contain("GROUP BY"));
Assert.That(result, Does.Contain("HAVING"));
Assert.That(result, Does.Contain("ORDER BY"));
}
[Test]
public void GenerateMermaidDiagram_WithWhereClause_UsesDecisionShape()
{
// Arrange
var query = new QueryBreakdown("*", "Products", "Price > 100");
// Act
var result = _generator.GenerateMermaidDiagram(query);
// Assert
Assert.That(result, Does.Contain("WHERE"));
Assert.That(result, Does.Contain("{"));
Assert.That(result, Does.Contain("}"));
}
[Test]
public void GenerateMermaidDiagram_ParsedQuery_GeneratesDiagram()
{
// Arrange
var sql = @"
SELECT u.ID, u.Name, u.Email
FROM Users u
WHERE u.Active = 1
ORDER BY u.Name";
var query = QueryBreakdown.Parse(sql);
// Act
var result = _generator.GenerateMermaidDiagram(query);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result, Does.Contain("mermaid"));
Assert.That(result, Does.Contain("SELECT"));
Assert.That(result.Length, Is.GreaterThan(100));
}
[Test]
public void GenerateMermaidDiagram_WithTitle_IncludesTitle()
{
// Arrange
var query = new QueryBreakdown("*", "Users");
// Act
var result = _generator.GenerateMermaidDiagram(query, "Test Query");
// Assert
Assert.That(result, Does.StartWith("### Test Query"));
}
[Test]
public void GenerateMermaidDiagram_WithoutTitle_NoTitle()
{
// Arrange
var query = new QueryBreakdown("*", "Users");
// Act
var result = _generator.GenerateMermaidDiagram(query);
// Assert
Assert.That(result, Does.Not.StartWith("###"));
Assert.That(result, Does.StartWith("```mermaid"));
}
[Test]
public void GenerateMermaidDiagram_WithLongClause_TruncatesText()
{
// Arrange
var longSelect = string.Join(", ", Enumerable.Range(1, 50).Select(i => $"Column{i}"));
var query = new QueryBreakdown(longSelect, "LargeTable");
// Act
var result = _generator.GenerateMermaidDiagram(query);
// Assert
Assert.That(result, Does.Contain("..."));
}
[Test]
public void GenerateMermaidDiagram_ISqlBreakdown_GeneratesSimpleDiagram()
{
// Arrange
var query = new QueryBreakdown("*", "Users");
query.SetupClauses.Add("CREATE TEMP TABLE #Temp (ID INT)");
// Act
var result = _generator.GenerateMermaidDiagram((Interfaces.ISqlBreakdown)query);
// Assert
Assert.That(result, Does.Contain("mermaid"));
Assert.That(result, Does.Contain("flowchart TD"));
Assert.That(result, Does.Contain("Users"));
}
}
@@ -0,0 +1,151 @@
using Strata.SqlTools.Breakdowns.SqlServer;
using Strata.SqlTools.Markdown.SqlServer;
namespace Strata.SqlTools.Markdown.Tests.SqlServer;
[TestFixture]
[Ignore("These tests are designed to generate markdown files from SQL queries in the Queries directory. They are not meant to be run as part of regular unit testing, but can be executed manually when needed.")]
[Category("MarkdownGeneration")]
public class QueryMarkdownGenerationTests
{
private QueryBreakdownGenerator _generator = null!;
private string _queriesSourcePath = null!;
private string _markdownOutputPath = null!;
[SetUp]
public void Setup()
{
_generator = new QueryBreakdownGenerator();
// Get the solution root directory
var testDirectory = TestContext.CurrentContext.TestDirectory;
var solutionRoot = Directory.GetParent(testDirectory)?.Parent?.Parent?.Parent?.Parent?.FullName;
if (solutionRoot == null)
throw new InvalidOperationException("Could not determine solution root directory");
_queriesSourcePath = Path.Combine(solutionRoot, "Queries");
_markdownOutputPath = Path.Combine(solutionRoot, "docs", "queries");
// Ensure output directory exists
if (!Directory.Exists(_markdownOutputPath))
{
Directory.CreateDirectory(_markdownOutputPath);
}
}
[Test]
public void GenerateMarkdownForAllQueries_CreatesMarkdownFiles()
{
// Arrange
Assert.That(Directory.Exists(_queriesSourcePath), Is.True,
$"Queries directory not found at: {_queriesSourcePath}");
var sqlFiles = Directory.GetFiles(_queriesSourcePath, "*.sql");
Assert.That(sqlFiles, Is.Not.Empty, "No SQL files found in Queries directory");
int successCount = 0;
int skippedCount = 0;
// Act & Assert for each file
foreach (var sqlFile in sqlFiles)
{
var fileName = Path.GetFileNameWithoutExtension(sqlFile);
var sqlContent = File.ReadAllText(sqlFile);
try
{
// Parse the SQL query
var queryBreakdown = QueryBreakdown.Parse(sqlContent);
// Generate markdown with the filename as title
var markdown = _generator.GenerateMermaidDiagram(queryBreakdown, fileName);
// Verify markdown was generated
Assert.That(markdown, Is.Not.Null);
Assert.That(markdown, Does.Contain("```mermaid"));
Assert.That(markdown, Does.Contain(fileName));
// Write to output file
var outputFile = Path.Combine(_markdownOutputPath, $"{fileName}.md");
File.WriteAllText(outputFile, markdown);
// Verify file was created
Assert.That(File.Exists(outputFile), Is.True,
$"Markdown file was not created: {outputFile}");
TestContext.WriteLine($"Generated: {fileName}.md");
successCount++;
}
catch (FormatException ex)
{
// Skip files that can't be parsed (e.g., partial queries with only WITH clauses)
TestContext.WriteLine($"Skipped: {fileName}.sql - {ex.Message}");
skippedCount++;
}
}
TestContext.WriteLine($"Generated {successCount} markdown files, skipped {skippedCount} files in {_markdownOutputPath}");
Assert.That(successCount, Is.GreaterThan(0), "At least one markdown file should be generated");
}
[Test]
public void GenerateMarkdownForAllQueries_IncludesQuerySource()
{
// Arrange
var sqlFiles = Directory.GetFiles(_queriesSourcePath, "*.sql");
Assert.That(sqlFiles, Is.Not.Empty);
int successCount = 0;
// Act & Assert
foreach (var sqlFile in sqlFiles)
{
var fileName = Path.GetFileNameWithoutExtension(sqlFile);
var sqlContent = File.ReadAllText(sqlFile);
try
{
var queryBreakdown = QueryBreakdown.Parse(sqlContent);
var markdown = _generator.GenerateMermaidDiagram(queryBreakdown, fileName);
// Add source SQL to the markdown
var fullMarkdown = $"{markdown}\n\n## Source SQL\n\n```sql\n{sqlContent}\n```\n";
var outputFile = Path.Combine(_markdownOutputPath, $"{fileName}.md");
File.WriteAllText(outputFile, fullMarkdown);
// Verify the output includes both diagram and source
var writtenContent = File.ReadAllText(outputFile);
Assert.That(writtenContent, Does.Contain("```mermaid"));
Assert.That(writtenContent, Does.Contain("## Source SQL"));
Assert.That(writtenContent, Does.Contain(sqlContent));
successCount++;
}
catch (FormatException)
{
// Skip files that can't be parsed
TestContext.WriteLine($"Skipped: {fileName}.sql (could not parse)");
}
}
Assert.That(successCount, Is.GreaterThan(0), "At least one markdown file should be generated");
}
[Test]
public void AllQueriesDirectory_Exists()
{
// Verify the Queries directory exists
Assert.That(Directory.Exists(_queriesSourcePath), Is.True,
$"Queries directory should exist at: {_queriesSourcePath}");
}
[Test]
public void OutputDirectory_IsCreated()
{
// Verify the output directory was created
Assert.That(Directory.Exists(_markdownOutputPath), Is.True,
$"Output directory should exist at: {_markdownOutputPath}");
}
}
@@ -0,0 +1,124 @@
using Strata.SqlTools.Breakdowns.SqlServer;
using Strata.SqlTools.Markdown.SqlServer;
namespace Strata.SqlTools.Markdown.Tests.SqlServer;
[TestFixture]
public class SqlStatementGeneratorTests
{
private SqlStatementGenerator _generator = null!;
[SetUp]
public void Setup()
{
_generator = new SqlStatementGenerator();
}
[Test]
public void GenerateSequenceDiagram_WithSimpleQuery_GeneratesSequence()
{
// Arrange
var query = new QueryBreakdown("*", "Users");
// Act
var result = _generator.GenerateSequenceDiagram(query);
// Assert
Assert.That(result, Does.Contain("```mermaid"));
Assert.That(result, Does.Contain("sequenceDiagram"));
Assert.That(result, Does.Contain("App->>DB"));
Assert.That(result, Does.Contain("DB-->>App"));
Assert.That(result, Does.Contain("```"));
}
[Test]
public void GenerateSequenceDiagram_WithSetupClauses_IncludesSetup()
{
// Arrange
var query = new QueryBreakdown("*", "Users");
query.SetupClauses.Add("CREATE TEMP TABLE #Temp (ID INT)");
// Act
var result = _generator.GenerateSequenceDiagram(query);
// Assert
Assert.That(result, Does.Contain("Setup Clauses"));
Assert.That(result, Does.Contain("activate DB"));
Assert.That(result, Does.Contain("deactivate DB"));
}
[Test]
public void GenerateSequenceDiagram_WithFinishClauses_IncludesFinish()
{
// Arrange
var query = new QueryBreakdown("*", "Users");
query.FinishClauses.Add("DROP TABLE #Temp");
// Act
var result = _generator.GenerateSequenceDiagram(query);
// Assert
Assert.That(result, Does.Contain("Finish Clauses"));
Assert.That(result, Does.Contain("Cleanup"));
}
[Test]
public void GenerateSequenceDiagram_WithTitle_IncludesTitle()
{
// Arrange
var query = new QueryBreakdown("*", "Users");
// Act
var result = _generator.GenerateSequenceDiagram(query, "Query Execution");
// Assert
Assert.That(result, Does.StartWith("### Query Execution"));
}
[Test]
public void GenerateEntityRelationshipDiagram_WithTables_GeneratesERDiagram()
{
// Arrange
var tables = new[] { "Users", "Orders", "Products" };
// Act
var result = _generator.GenerateEntityRelationshipDiagram(tables);
// Assert
Assert.That(result, Does.Contain("```mermaid"));
Assert.That(result, Does.Contain("erDiagram"));
Assert.That(result, Does.Contain("Users"));
Assert.That(result, Does.Contain("Orders"));
Assert.That(result, Does.Contain("Products"));
Assert.That(result, Does.Contain("```"));
}
[Test]
public void GenerateEntityRelationshipDiagram_WithTitle_IncludesTitle()
{
// Arrange
var tables = new[] { "Users", "Orders" };
// Act
var result = _generator.GenerateEntityRelationshipDiagram(tables, "Database Schema");
// Assert
Assert.That(result, Does.StartWith("### Database Schema"));
}
[Test]
public void GenerateEntityRelationshipDiagram_CleansTableNames()
{
// Arrange
var tables = new[] { "[dbo].[Users]", "schema.Orders" };
// Act
var result = _generator.GenerateEntityRelationshipDiagram(tables);
// Assert
Assert.That(result, Does.Contain("dbo_Users"));
Assert.That(result, Does.Contain("schema_Orders"));
Assert.That(result, Does.Not.Contain("["));
Assert.That(result, Does.Not.Contain("]"));
}
}