chore: initial git load of code space
This commit is contained in:
@@ -0,0 +1,282 @@
|
||||
using Strata.SqlTools.Breakdowns.Snowflake;
|
||||
using Strata.SqlTools.SqlBreakdown.Classes;
|
||||
|
||||
namespace Strata.SqlTools.Snowflake.Tests;
|
||||
|
||||
[TestFixture]
|
||||
public class CTEColumnListTests
|
||||
{
|
||||
#region Basic Column List Tests
|
||||
|
||||
[Test]
|
||||
public void WithClause_ColumnList_CanBeSet()
|
||||
{
|
||||
// Arrange
|
||||
var cte = new QueryBreakdown("id, name, email", "users");
|
||||
var withClause = new WithClause("user_summary", cte)
|
||||
{
|
||||
ColumnList = new List<string> { "user_id", "user_name", "user_email" }
|
||||
};
|
||||
|
||||
// Act & Assert
|
||||
Assert.That(withClause.ColumnList, Has.Count.EqualTo(3));
|
||||
Assert.That(withClause.ColumnList[0], Is.EqualTo("user_id"));
|
||||
Assert.That(withClause.ColumnList[1], Is.EqualTo("user_name"));
|
||||
Assert.That(withClause.ColumnList[2], Is.EqualTo("user_email"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithColumnList_IncludesColumnsInWithClauseName()
|
||||
{
|
||||
// Arrange
|
||||
var cte = new QueryBreakdown("id, name, email", "users", "active = TRUE");
|
||||
var mainQuery = new QueryBreakdown("*", "active_users");
|
||||
|
||||
var withClause = new WithClause("active_users", cte)
|
||||
{
|
||||
ColumnList = new List<string> { "user_id", "user_name", "user_email" }
|
||||
};
|
||||
mainQuery.AddWithClause(withClause);
|
||||
|
||||
// Act
|
||||
var sql = mainQuery.GetSql();
|
||||
|
||||
// Assert
|
||||
Assert.That(sql, Contains.Substring("active_users (user_id, user_name, user_email)"),
|
||||
"SQL should include column list in CTE definition");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithoutColumnList_DoesNotIncludeParens()
|
||||
{
|
||||
// Arrange
|
||||
var cte = new QueryBreakdown("id, name, email", "users");
|
||||
var mainQuery = new QueryBreakdown("*", "all_users");
|
||||
|
||||
var withClause = new WithClause("all_users", cte)
|
||||
{
|
||||
ColumnList = null
|
||||
};
|
||||
mainQuery.AddWithClause(withClause);
|
||||
|
||||
// Act
|
||||
var sql = mainQuery.GetSql();
|
||||
|
||||
// Assert
|
||||
Assert.That(sql, Contains.Substring("all_users AS"), "Without column list, should use table name only");
|
||||
Assert.That(sql, Does.Not.Contain("all_users ()"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithEmptyColumnList_DoesNotIncludeParens()
|
||||
{
|
||||
// Arrange
|
||||
var cte = new QueryBreakdown("id, name", "users");
|
||||
var mainQuery = new QueryBreakdown("*", "data");
|
||||
|
||||
var withClause = new WithClause("data", cte)
|
||||
{
|
||||
ColumnList = new List<string>()
|
||||
};
|
||||
mainQuery.AddWithClause(withClause);
|
||||
|
||||
// Act
|
||||
var sql = mainQuery.GetSql();
|
||||
|
||||
// Assert
|
||||
Assert.That(sql, Contains.Substring("data AS"));
|
||||
Assert.That(sql, Does.Not.Contain("data ()"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Multi-CTE Column List Tests
|
||||
|
||||
[Test]
|
||||
public void GetSql_WithMultipleCTEsWithColumnLists_IncludesAllLists()
|
||||
{
|
||||
// Arrange
|
||||
var cte1 = new QueryBreakdown("id, name", "users");
|
||||
var cte2 = new QueryBreakdown("user_id, order_count", "orders");
|
||||
|
||||
var mainQuery = new QueryBreakdown("*", "results");
|
||||
|
||||
var withClause1 = new WithClause("active_users", cte1)
|
||||
{
|
||||
ColumnList = new List<string> { "user_id", "user_name" }
|
||||
};
|
||||
|
||||
var withClause2 = new WithClause("user_orders", cte2)
|
||||
{
|
||||
ColumnList = new List<string> { "uid", "order_count" }
|
||||
};
|
||||
|
||||
mainQuery.AddWithClause(withClause1);
|
||||
mainQuery.AddWithClause(withClause2);
|
||||
|
||||
// Act
|
||||
var sql = mainQuery.GetSql();
|
||||
|
||||
// Assert
|
||||
Assert.That(sql, Contains.Substring("active_users (user_id, user_name)"));
|
||||
Assert.That(sql, Contains.Substring("user_orders (uid, order_count)"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Column List with Parameters
|
||||
|
||||
[Test]
|
||||
public void ColumnList_PreservesSnowflakeParameters()
|
||||
{
|
||||
// Arrange
|
||||
var cte = new QueryBreakdown("id, name, salary", "employees", "salary > :MinSalary");
|
||||
cte.AddParameter("MinSalary", 50000);
|
||||
|
||||
var mainQuery = new QueryBreakdown("*", "high_earners");
|
||||
|
||||
var withClause = new WithClause("high_earners", cte)
|
||||
{
|
||||
ColumnList = new List<string> { "emp_id", "emp_name", "emp_salary" }
|
||||
};
|
||||
mainQuery.AddWithClause(withClause);
|
||||
|
||||
// Act
|
||||
var sql = mainQuery.GetSql();
|
||||
var merged = mainQuery.GetMergedParameters();
|
||||
|
||||
// Assert
|
||||
Assert.That(sql, Contains.Substring("high_earners (emp_id, emp_name, emp_salary)"));
|
||||
var keys = merged.Keys.ToList();
|
||||
Assert.That(keys.Any(k => k.Contains("MinSalary")), "Parameters should be preserved with column list");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Column List with Recursive CTEs
|
||||
|
||||
[Test]
|
||||
public void ColumnList_WorksWithRecursiveCTE()
|
||||
{
|
||||
// Arrange
|
||||
var anchorQuery = new QueryBreakdown("id, manager_id, name, 1 as level", "employees", "manager_id IS NULL");
|
||||
var recursiveQuery = new QueryBreakdown(
|
||||
"e.id, e.manager_id, e.name, h.level + 1",
|
||||
"employees e INNER JOIN hierarchy h ON e.manager_id = h.id"
|
||||
);
|
||||
|
||||
var mainQuery = new QueryBreakdown("*", "hierarchy");
|
||||
|
||||
var withClause = new WithClause("hierarchy", anchorQuery)
|
||||
{
|
||||
IsRecursive = true,
|
||||
RecursiveQuery = recursiveQuery,
|
||||
ColumnList = new List<string> { "emp_id", "mgr_id", "emp_name", "lvl" }
|
||||
};
|
||||
mainQuery.AddWithClause(withClause);
|
||||
|
||||
// Act
|
||||
var sql = mainQuery.GetSql();
|
||||
|
||||
// Assert
|
||||
Assert.That(sql, Contains.Substring("WITH RECURSIVE"));
|
||||
Assert.That(sql, Contains.Substring("hierarchy (emp_id, mgr_id, emp_name, lvl)"));
|
||||
Assert.That(sql, Contains.Substring("UNION ALL"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Column List Length and Naming
|
||||
|
||||
[Test]
|
||||
public void ColumnList_CanHaveManyColumns()
|
||||
{
|
||||
// Arrange
|
||||
var cte = new QueryBreakdown("col1, col2, col3, col4, col5, col6, col7, col8", "source");
|
||||
var mainQuery = new QueryBreakdown("*", "results");
|
||||
|
||||
var columns = new List<string>
|
||||
{
|
||||
"c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"
|
||||
};
|
||||
|
||||
var withClause = new WithClause("data_cte", cte)
|
||||
{
|
||||
ColumnList = columns
|
||||
};
|
||||
mainQuery.AddWithClause(withClause);
|
||||
|
||||
// Act
|
||||
var sql = mainQuery.GetSql();
|
||||
|
||||
// Assert
|
||||
var expectedColumns = string.Join(", ", columns);
|
||||
Assert.That(sql, Contains.Substring($"data_cte ({expectedColumns})"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ColumnList_PreservesColumnOrder()
|
||||
{
|
||||
// Arrange
|
||||
var cte = new QueryBreakdown("a, b, c", "source");
|
||||
var mainQuery = new QueryBreakdown("*", "output");
|
||||
|
||||
var columns = new List<string> { "z", "y", "x" };
|
||||
var withClause = new WithClause("ordered_cte", cte)
|
||||
{
|
||||
ColumnList = columns
|
||||
};
|
||||
mainQuery.AddWithClause(withClause);
|
||||
|
||||
// Act
|
||||
var sql = mainQuery.GetSql();
|
||||
|
||||
// Assert
|
||||
Assert.That(sql, Contains.Substring("ordered_cte (z, y, x)"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Real-World Scenarios
|
||||
|
||||
[Test]
|
||||
public void ColumnList_SnowflakeDataWarehouseScenario()
|
||||
{
|
||||
// Scenario: Data warehouse aggregation with renamed fact columns
|
||||
// Arrange
|
||||
var factData = new QueryBreakdown(
|
||||
"date_sk, product_sk, customer_sk, quantity, revenue",
|
||||
"fact_sales",
|
||||
"date_sk >= :StartDateSk AND revenue >= :MinRevenue"
|
||||
);
|
||||
factData.AddParameter("StartDateSk", 20240101);
|
||||
factData.AddParameter("MinRevenue", 5000);
|
||||
|
||||
var mainQuery = new QueryBreakdown("*", "revenue_summary");
|
||||
|
||||
var withClause = new WithClause("high_value_sales", factData)
|
||||
{
|
||||
ColumnList = new List<string>
|
||||
{
|
||||
"sale_date_key",
|
||||
"product_key",
|
||||
"customer_key",
|
||||
"units_sold",
|
||||
"total_revenue"
|
||||
}
|
||||
};
|
||||
mainQuery.AddWithClause(withClause);
|
||||
|
||||
// Act
|
||||
var sql = mainQuery.GetSql();
|
||||
var params_all = mainQuery.GetMergedParameters();
|
||||
|
||||
// Assert
|
||||
Assert.That(sql, Contains.Substring("high_value_sales (sale_date_key, product_key, customer_key, units_sold, total_revenue)"));
|
||||
var paramKeys = params_all.Keys.ToList();
|
||||
Assert.That(paramKeys.Any(k => k.Contains("StartDateSk")));
|
||||
Assert.That(paramKeys.Any(k => k.Contains("MinRevenue")));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user