Skip to content

Commit

Permalink
Merge pull request #405 from mk3008/402-add-class-function-and-proper…
Browse files Browse the repository at this point in the history
…ty-comments

Add comment
  • Loading branch information
mk3008 authored May 7, 2024
2 parents 02a412c + 1d2f632 commit f2cb9b7
Show file tree
Hide file tree
Showing 24 changed files with 1,400 additions and 121 deletions.
41 changes: 41 additions & 0 deletions src/Carbunql/Building/CaseExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,86 @@

namespace Carbunql.Building;

/// <summary>
/// Static class providing extension methods for constructing CASE expressions.
/// </summary>
public static class CaseExtension
{
/// <summary>
/// Adds a WHEN clause to the CASE expression with the specified condition as a string.
/// </summary>
/// <param name="source">The CASE expression.</param>
/// <param name="condition">The condition for the WHEN clause.</param>
/// <returns>The created WHEN expression.</returns>
public static WhenExpression When(this CaseExpression source, string condition)
{
var w = new WhenExpression(ValueParser.Parse(condition), new LiteralValue("null"));
source.WhenExpressions.Add(w);
return w;
}

/// <summary>
/// Adds a WHEN clause to the CASE expression with the specified condition.
/// </summary>
/// <param name="source">The CASE expression.</param>
/// <param name="condition">The condition for the WHEN clause.</param>
/// <returns>The created WHEN expression.</returns>
public static WhenExpression When(this CaseExpression source, ValueBase condition)
{
var w = new WhenExpression(condition, new LiteralValue("null"));
source.WhenExpressions.Add(w);
return w;
}

/// <summary>
/// Adds a WHEN clause to the CASE expression using a condition builder function.
/// </summary>
/// <param name="source">The CASE expression.</param>
/// <param name="builder">The function to build the condition.</param>
/// <returns>The created WHEN expression.</returns>
public static WhenExpression When(this CaseExpression source, Func<ValueBase> builder)
{
var w = new WhenExpression(builder(), new LiteralValue("null"));
source.WhenExpressions.Add(w);
return w;
}

/// <summary>
/// Sets the THEN value of the WHEN expression to the specified string value.
/// </summary>
/// <param name="source">The WHEN expression.</param>
/// <param name="value">The string value for the THEN clause.</param>
public static void Then(this WhenExpression source, string value)
{
source.SetValue(ValueParser.Parse(value));
}

/// <summary>
/// Sets the THEN value of the WHEN expression.
/// </summary>
/// <param name="source">The WHEN expression.</param>
/// <param name="value">The value for the THEN clause.</param>
public static void Then(this WhenExpression source, ValueBase value)
{
source.SetValue(value);
}

/// <summary>
/// Adds an ELSE clause to the CASE expression with the specified string value.
/// </summary>
/// <param name="source">The CASE expression.</param>
/// <param name="value">The string value for the ELSE clause.</param>
public static void Else(this CaseExpression source, string value)
{
var w = new WhenExpression(ValueParser.Parse(value));
source.WhenExpressions.Add(w);
}

/// <summary>
/// Adds an ELSE clause to the CASE expression.
/// </summary>
/// <param name="source">The CASE expression.</param>
/// <param name="value">The value for the ELSE clause.</param>
public static void Else(this CaseExpression source, ValueBase value)
{
var w = new WhenExpression(value);
Expand Down
23 changes: 20 additions & 3 deletions src/Carbunql/Building/CommonTableExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,36 @@

namespace Carbunql.Building;

/// <summary>
/// Static class providing extension methods for common table expressions (CTEs).
/// </summary>
public static class CommonTableExtension
{
/// <summary>
/// Sets the alias for the common table expression (CTE).
/// </summary>
/// <param name="source">The common table expression.</param>
/// <param name="alias">The alias to set.</param>
/// <returns>The modified common table expression.</returns>
public static CommonTable As(this CommonTable source, string alias)
{
source.SetAlias(alias);
return source;
}

/// <summary>
/// Converts the common table expression (CTE) to a physical table.
/// </summary>
/// <param name="source">The common table expression.</param>
/// <returns>A physical table.</returns>
public static PhysicalTable ToPhysicalTable(this CommonTable source)
{
var t = new PhysicalTable(source.Alias);
t.ColumnNames ??= new();
foreach (var item in source.GetColumnNames()) t.ColumnNames.Add(item);
t.ColumnNames ??= new List<string>();
foreach (var item in source.GetColumnNames())
{
t.ColumnNames.Add(item);
}
return t;
}
}
}
55 changes: 50 additions & 5 deletions src/Carbunql/Building/DatePivotQueryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,45 @@

namespace Carbunql.Building;

/// <summary>
/// Provides functionality to execute pivot queries based on date columns.
/// </summary>
public class DatePivotQueryBuilder
{
/// <summary>
/// Gets or sets the month for which the pivot query is executed.
/// </summary>
public DateTime Month { get; set; }

/// <summary>
/// Gets or sets the date format used in the pivot query.
/// </summary>
public string DateFormat { get; set; } = "dd";

/// <summary>
/// Gets or sets a value indicating whether the pivot query includes summary columns.
/// </summary>
public bool HasSummary { get; set; } = true;

/// <summary>
/// Gets or sets the alias for the data source in the pivot query.
/// </summary>
public string DatasourceAlias { get; set; } = "datasource";

/// <summary>
/// Gets or sets the alias for the matrix table in the pivot query.
/// </summary>
public string MatrixAlias { get; set; } = "matrix";

/// <summary>
/// Executes the pivot query.
/// </summary>
/// <param name="sql">The SQL query.</param>
/// <param name="dateColumn">The name of the date column in the SQL query.</param>
/// <param name="groupColumns">The list of group columns in the SQL query.</param>
/// <param name="valueColumn">The name of the value column in the SQL query.</param>
/// <param name="columnHeaders">Optional. The list of column headers for the pivot table.</param>
/// <returns>The executed pivot query.</returns>
public IReadQuery Execute(string sql, string dateColumn, IList<string> groupColumns, string valueColumn, List<string>? columnHeaders = null)
{
var (cteq, ds) = QueryParser.Parse(sql).ToCTE(DatasourceAlias);
Expand All @@ -26,7 +53,10 @@ public IReadQuery Execute(string sql, string dateColumn, IList<string> groupColu
var (f, d) = sq.From(ds).As("d");
var m = f.InnerJoin(matrix).As("m").On(d, dateColumn);

foreach (var item in groupColumns) sq.Select(d, item);
foreach (var item in groupColumns)
{
sq.Select(d, item);
}

var ca = matrix!.ColumnAliases;
foreach (var item in ca!.Where(x => x.ToText() != dateColumn).Select(x => x.ToText()))
Expand All @@ -36,13 +66,25 @@ public IReadQuery Execute(string sql, string dateColumn, IList<string> groupColu
sq.Select(new FunctionValue("sum", c)).As(item);
}

foreach (var item in groupColumns) sq.Group(d, item);
foreach (var item in groupColumns)
{
sq.Group(d, item);
}

foreach (var item in groupColumns) sq.Order(d, item);
foreach (var item in groupColumns)
{
sq.Order(d, item);
}

return cteq;
}

/// <summary>
/// Creates the matrix table for the pivot query.
/// </summary>
/// <param name="ymColumn">The name of the year-month column.</param>
/// <param name="columnHeaders">Optional. The list of column headers for the matrix table.</param>
/// <returns>The created matrix table.</returns>
private CommonTable CreateMatrixTable(string ymColumn, List<string>? columnHeaders)
{
var startdate = new DateTime(Month.Year, Month.Month, 1);
Expand Down Expand Up @@ -70,8 +112,11 @@ private CommonTable CreateMatrixTable(string ymColumn, List<string>? columnHeade

var ct = MatrixEditor.Create(ymColumn, keyValues, columnHeaders);

if (HasSummary) MatrixEditor.AddTotalSummaryColumn(ct);
if (HasSummary)
{
MatrixEditor.AddTotalSummaryColumn(ct);
}

return ct;
}
}
}
43 changes: 36 additions & 7 deletions src/Carbunql/Building/DiffQueryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,30 @@

namespace Carbunql.Building;

/// <summary>
/// Provides functionality to generate a query that compares two SQL select queries.
/// </summary>
public class DiffQueryBuilder
{
/// <summary>
/// Executes the diff query generation process.
/// </summary>
/// <param name="expectsql">The expected SQL select query.</param>
/// <param name="actualsql">The actual SQL select query.</param>
/// <param name="keys">The keys used to join the two select queries.</param>
/// <returns>A SelectQuery representing the differences between the two input queries.</returns>
public static SelectQuery Execute(string expectsql, string actualsql, string[] keys)
{
return Execute(SelectQueryParser.Parse(expectsql), SelectQueryParser.Parse(actualsql), keys);
}

/// <summary>
/// Executes the diff query generation process.
/// </summary>
/// <param name="expectsql">The expected SelectQuery.</param>
/// <param name="actualsql">The actual SelectQuery.</param>
/// <param name="keys">The keys used to join the two queries.</param>
/// <returns>A SelectQuery representing the differences between the two input queries.</returns>
public static SelectQuery Execute(SelectQuery expectsql, SelectQuery actualsql, string[] keys)
{
var sq = GenerateQueryAsChanged(expectsql, actualsql, keys);
Expand All @@ -27,10 +44,13 @@ private static SelectQuery GenerateQueryAsChanged(SelectQuery expectsq, SelectQu
var a = from.InnerJoin(actualsq).As("actual").On(e, keys);

var expectColumns = expectsq.SelectClause!.Select(x => x.Alias).Where(x => !keys.Contains(x));
var acutalColumns = actualsq.SelectClause!.Select(x => x.Alias).Where(x => !keys.Contains(x));
var commonColumns = expectColumns.Where(x => acutalColumns.Contains(x));
var actualColumns = actualsq.SelectClause!.Select(x => x.Alias).Where(x => !keys.Contains(x));
var commonColumns = expectColumns.Where(x => actualColumns.Contains(x));

foreach (var item in keys) sq.Select(e, item);
foreach (var item in keys)
{
sq.Select(e, item);
}
sq.Select("'update'").As("diff_type");
CaseExpression? exp = null;

Expand All @@ -55,7 +75,10 @@ private static SelectQuery GenerateQueryAsChanged(SelectQuery expectsq, SelectQu
}
}

if (exp != null) sq.Select(exp).As("remarks");
if (exp != null)
{
sq.Select(exp).As("remarks");
}

var q = new SelectQuery();
var (_, t) = q.From(sq).As("t");
Expand All @@ -72,7 +95,10 @@ private static SelectQuery GenerateQueryAsDeleted(SelectQuery expectsq, SelectQu

var a = from.LeftJoin(actualsq).As("actual").On(e, keys);

foreach (var item in keys) sq.Select(e, item);
foreach (var item in keys)
{
sq.Select(e, item);
}
sq.Select("'delete'").As("diff_type");
sq.Select("'*deleted'").As("remarks");
sq.Where(a, keys[0]).IsNull();
Expand All @@ -87,11 +113,14 @@ private static SelectQuery GenerateQueryAsAdded(SelectQuery expectsq, SelectQuer

var e = from.LeftJoin(expectsq).As("expect").On(a, keys);

foreach (var item in keys) sq.Select(a, item);
foreach (var item in keys)
{
sq.Select(a, item);
}
sq.Select("'insert'").As("diff_type");
sq.Select("'*added'").As("remarks");
sq.Where(e, keys[0]).IsNull();

return sq;
}
}
}
Loading

0 comments on commit f2cb9b7

Please sign in to comment.