Skip to content

Commit

Permalink
Merge pull request #318 from mk3008/302-request-windowclause-build-im…
Browse files Browse the repository at this point in the history
…provement

302 request windowclause build improvement
  • Loading branch information
mk3008 authored Jan 31, 2024
2 parents e27daec + 808a7b0 commit 40b684b
Show file tree
Hide file tree
Showing 7 changed files with 240 additions and 25 deletions.
6 changes: 6 additions & 0 deletions src/Carbunql/Building/SelectClauseExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,10 @@ public static void Order(this SelectQuery source, string table, string column)
source.OrderClause ??= new();
source.OrderClause.Add(item);
}

public static void Window(this SelectQuery source, NamedWindowDefinition namedWindow)
{
source.WindowClause ??= new();
source.WindowClause.Add(namedWindow);
}
}
129 changes: 108 additions & 21 deletions src/Carbunql/Building/WindowFunctionExtension.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,121 @@
using Carbunql.Clauses;
using Carbunql.Values;

namespace Carbunql.Building;

public static class WindowFunctionExtension
{
public static void AddPartition(this OverClause source, ValueBase partition)
{
source.WindowDefinition ??= new();
source.WindowDefinition.PartitionBy ??= new();
source.WindowDefinition.PartitionBy.Add(partition);
}
public static void Partition(this OverClause source, ValueBase partition)
{
source.WindowDefinition ??= new();
source.WindowDefinition.Partition(partition);
}

public static void Partition(this OverClause source, Func<ValueBase> partitionbuilder)
{
source.WindowDefinition ??= new();
source.WindowDefinition.Partition(partitionbuilder());
}

public static void Partition(this OverClause source, SelectableItem order)
{
source.WindowDefinition ??= new();
source.WindowDefinition.Partition(order.Value);
}

public static void Order(this OverClause source, ColumnValue order)
{
source.WindowDefinition ??= new();
source.WindowDefinition.Order(order.ToSortable());
}

public static void Order(this OverClause source, SortableItem order)
{
source.WindowDefinition ??= new();
source.WindowDefinition.Order(order);
}

public static void Order(this OverClause source, Func<SortableItem> orderbuilder)
{
source.WindowDefinition ??= new();
source.WindowDefinition.Order(orderbuilder());
}

public static void Partition(this WindowDefinition source, ValueBase partition)
{
source.PartitionBy ??= new();
source.PartitionBy.Add(partition);
}

public static void Partition(this WindowDefinition source, Func<ValueBase> partitionbuilder)
{
source.PartitionBy ??= new();
source.PartitionBy.Add(partitionbuilder());
}

public static void Partition(this WindowDefinition source, SelectableItem order)
{
source.PartitionBy ??= new();
source.PartitionBy.Add(order.Value);
}

public static void Order(this WindowDefinition source, ColumnValue order)
{
source.OrderBy ??= new();
source.OrderBy.Add(order.ToSortable());
}

public static void Order(this WindowDefinition source, SortableItem order)
{
source.OrderBy ??= new();
source.OrderBy.Add(order);
}

public static void Order(this WindowDefinition source, Func<SortableItem> orderbuilder)
{
source.OrderBy ??= new();
source.OrderBy.Add(orderbuilder());
}

public static void Partition(this NamedWindowDefinition source, ValueBase partition)
{
source.WindowDefinition ??= new();
source.WindowDefinition.Partition(partition);
}

public static void Partition(this NamedWindowDefinition source, Func<ValueBase> partitionbuilder)
{
source.WindowDefinition ??= new();
source.WindowDefinition.Partition(partitionbuilder());
}

public static void Partition(this NamedWindowDefinition source, SelectableItem order)
{
source.WindowDefinition ??= new();
source.WindowDefinition.Partition(order.Value);
}

public static void Order(this NamedWindowDefinition source, ColumnValue order)
{
source.WindowDefinition ??= new();
source.WindowDefinition.Order(order.ToSortable());
}

public static void AddPartition(this OverClause source, Func<ValueBase> partitionbuilder)
{
public static void Order(this NamedWindowDefinition source, SelectableItem order)
{
source.WindowDefinition ??= new();
source.WindowDefinition.PartitionBy ??= new();
source.WindowDefinition.PartitionBy.Add(partitionbuilder());
}
source.WindowDefinition.Order(order.Value.ToSortable());
}

public static void AddOrder(this OverClause source, SortableItem order)
{
public static void Order(this NamedWindowDefinition source, SortableItem order)
{
source.WindowDefinition ??= new();
source.WindowDefinition.OrderBy ??= new();
source.WindowDefinition.OrderBy.Add(order);
}
source.WindowDefinition.Order(order);
}

public static void AddOrder(this OverClause source, Func<SortableItem> orderbuilder)
{
public static void Order(this NamedWindowDefinition source, Func<SortableItem> orderbuilder)
{
source.WindowDefinition ??= new();
source.WindowDefinition.OrderBy ??= new();
source.WindowDefinition.OrderBy.Add(orderbuilder());
}
source.WindowDefinition.Order(orderbuilder());
}
}
6 changes: 6 additions & 0 deletions src/Carbunql/Clauses/NamedWindowDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ public NamedWindowDefinition()
WindowDefinition = null!;
}

public NamedWindowDefinition(string alias)
{
Alias = alias;
WindowDefinition = null!;
}

public NamedWindowDefinition(string alias, WindowDefinition definition)
{
Alias = alias;
Expand Down
5 changes: 5 additions & 0 deletions src/Carbunql/Clauses/OverClause.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ public OverClause(WindowDefinition definition)
WindowDefinition = definition;
}

public OverClause(NamedWindowDefinition definition)
{
WindowDefinition = new WindowDefinition(definition.Alias);
}

public WindowDefinition WindowDefinition { get; set; }

public IEnumerable<CommonTable> GetCommonTables()
Expand Down
4 changes: 2 additions & 2 deletions test/Carbunql.Building.Test/FunctionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ public void RowNumberTest()
sq.Select(() =>
{
var wf = new OverClause();
wf.AddPartition(new ColumnValue(a, "parent_id"));
wf.AddOrder(new ColumnValue(a, "id").ToSortable());
wf.Partition(new ColumnValue(a, "parent_id"));
wf.Order(new ColumnValue(a, "id").ToSortable());
return new FunctionValue("row_number", wf);
}).As("val");

Expand Down
4 changes: 2 additions & 2 deletions test/Carbunql.Building.Test/SerializeTest.ValueBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,8 @@ public void QueryContainer()
public void WindowFunction()
{
var win = new OverClause();
win.AddPartition(new ColumnValue("shop_id"));
win.AddOrder(new Clauses.SortableItem(new ColumnValue("order_id")));
win.Partition(new ColumnValue("shop_id"));
win.Order(new SortableItem(new ColumnValue("order_id")));

var sq = new FunctionValue("row_number", win);

Expand Down
111 changes: 111 additions & 0 deletions test/Carbunql.Building.Test/WindowTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
using Carbunql.Clauses;
using Carbunql.Values;
using Xunit.Abstractions;

namespace Carbunql.Building.Test;

public class WindowTest
{
private readonly QueryCommandMonitor Monitor;

public WindowTest(ITestOutputHelper output)
{
Monitor = new QueryCommandMonitor(output);
}

[Fact]
public void Default()
{
var sq = new SelectQuery();
var (_, a) = sq.From("table_a").As("a");

var pc = new PartitionClause
{
new ColumnValue(a, "name")
};
var oc = new OrderClause {
new ColumnValue(a, "a_id").ToSortable()
};
var wd = new WindowDefinition(pc, oc);
var w1 = new NamedWindowDefinition("w1", wd);

sq.WindowClause ??= new();
sq.WindowClause.Add(w1);

sq.Select(new FunctionValue("row_number", new OverClause(w1))).As("row_num");

Monitor.Log(sq);

var expect = @"SELECT
ROW_NUMBER() OVER w1 AS row_num
FROM
table_a AS a
WINDOW
w1 AS (
PARTITION BY
a.name
ORDER BY
a.a_id
)";

Assert.Equal(expect, sq.ToText().ToString(), true, true, true);
}

[Fact]
public void NamedWindow()
{
var sq = new SelectQuery();
var (_, a) = sq.From("table_a").As("a");

var w = new NamedWindowDefinition("w1");
w.Partition(new ColumnValue(a, "name"));
w.Order(new ColumnValue(a, "a_id"));

sq.Window(w);

sq.Select(new FunctionValue("row_number", new OverClause(w))).As("row_num");

Monitor.Log(sq);

var expect = @"SELECT
ROW_NUMBER() OVER w1 AS row_num
FROM
table_a AS a
WINDOW
w1 AS (
PARTITION BY
a.name
ORDER BY
a.a_id
)";

Assert.Equal(expect, sq.ToText().ToString(), true, true, true);
}

[Fact]
public void Window()
{
var sq = new SelectQuery();
var (_, a) = sq.From("table_a").As("a");

var w = new WindowDefinition();
w.Partition(new ColumnValue(a, "name"));
w.Order(new ColumnValue(a, "a_id"));

sq.Select(new FunctionValue("row_number", new OverClause(w))).As("row_num");

Monitor.Log(sq);

var expect = @"SELECT
ROW_NUMBER() OVER(
PARTITION BY
a.name
ORDER BY
a.a_id
) AS row_num
FROM
table_a AS a";

Assert.Equal(expect, sq.ToText().ToString(), true, true, true);
}
}

0 comments on commit 40b684b

Please sign in to comment.