From ba020514f8ddd57dcd05ccc7dbc3466699561265 Mon Sep 17 00:00:00 2001 From: mk3008 Date: Wed, 31 Jan 2024 22:42:49 +0900 Subject: [PATCH 1/2] Add NamedWindow test --- .../Building/SelectClauseExtension.cs | 6 + .../Building/WindowFunctionExtension.cs | 129 +++++++++++++++--- src/Carbunql/Clauses/NamedWindowDefinition.cs | 6 + src/Carbunql/Clauses/OverClause.cs | 5 + test/Carbunql.Building.Test/WindowTest.cs | 84 ++++++++++++ 5 files changed, 209 insertions(+), 21 deletions(-) create mode 100644 test/Carbunql.Building.Test/WindowTest.cs diff --git a/src/Carbunql/Building/SelectClauseExtension.cs b/src/Carbunql/Building/SelectClauseExtension.cs index 4be2bb6d..152c99b9 100644 --- a/src/Carbunql/Building/SelectClauseExtension.cs +++ b/src/Carbunql/Building/SelectClauseExtension.cs @@ -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); + } } \ No newline at end of file diff --git a/src/Carbunql/Building/WindowFunctionExtension.cs b/src/Carbunql/Building/WindowFunctionExtension.cs index 91b5732c..337db3c7 100644 --- a/src/Carbunql/Building/WindowFunctionExtension.cs +++ b/src/Carbunql/Building/WindowFunctionExtension.cs @@ -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 AddPartition(this OverClause source, ValueBase partition) + { + source.WindowDefinition ??= new(); + source.WindowDefinition.AddPartition(partition); + } + + public static void AddPartition(this OverClause source, Func partitionbuilder) + { + source.WindowDefinition ??= new(); + source.WindowDefinition.AddPartition(partitionbuilder()); + } + + public static void AddPartition(this OverClause source, SelectableItem order) + { + source.WindowDefinition ??= new(); + source.WindowDefinition.AddPartition(order.Value); + } + + public static void AddOrder(this OverClause source, ColumnValue order) + { + source.WindowDefinition ??= new(); + source.WindowDefinition.AddOrder(order.ToSortable()); + } + + public static void AddOrder(this OverClause source, SortableItem order) + { + source.WindowDefinition ??= new(); + source.WindowDefinition.AddOrder(order); + } + + public static void AddOrder(this OverClause source, Func orderbuilder) + { + source.WindowDefinition ??= new(); + source.WindowDefinition.AddOrder(orderbuilder()); + } + + public static void AddPartition(this WindowDefinition source, ValueBase partition) + { + source.PartitionBy ??= new(); + source.PartitionBy.Add(partition); + } + + public static void AddPartition(this WindowDefinition source, Func partitionbuilder) + { + source.PartitionBy ??= new(); + source.PartitionBy.Add(partitionbuilder()); + } + + public static void AddPartition(this WindowDefinition source, SelectableItem order) + { + source.PartitionBy ??= new(); + source.PartitionBy.Add(order.Value); + } + + public static void AddOrder(this WindowDefinition source, ColumnValue order) + { + source.OrderBy ??= new(); + source.OrderBy.Add(order.ToSortable()); + } + + public static void AddOrder(this WindowDefinition source, SortableItem order) + { + source.OrderBy ??= new(); + source.OrderBy.Add(order); + } + + public static void AddOrder(this WindowDefinition source, Func orderbuilder) + { + source.OrderBy ??= new(); + source.OrderBy.Add(orderbuilder()); + } + + public static void AddPartition(this NamedWindowDefinition source, ValueBase partition) + { + source.WindowDefinition ??= new(); + source.WindowDefinition.AddPartition(partition); + } + + public static void AddPartition(this NamedWindowDefinition source, Func partitionbuilder) + { + source.WindowDefinition ??= new(); + source.WindowDefinition.AddPartition(partitionbuilder()); + } + + public static void AddPartition(this NamedWindowDefinition source, SelectableItem order) + { + source.WindowDefinition ??= new(); + source.WindowDefinition.AddPartition(order.Value); + } + + public static void AddOrder(this NamedWindowDefinition source, ColumnValue order) + { + source.WindowDefinition ??= new(); + source.WindowDefinition.AddOrder(order.ToSortable()); + } - public static void AddPartition(this OverClause source, Func partitionbuilder) - { + public static void AddOrder(this NamedWindowDefinition source, SelectableItem order) + { source.WindowDefinition ??= new(); - source.WindowDefinition.PartitionBy ??= new(); - source.WindowDefinition.PartitionBy.Add(partitionbuilder()); - } + source.WindowDefinition.AddOrder(order.Value.ToSortable()); + } - public static void AddOrder(this OverClause source, SortableItem order) - { + public static void AddOrder(this NamedWindowDefinition source, SortableItem order) + { source.WindowDefinition ??= new(); - source.WindowDefinition.OrderBy ??= new(); - source.WindowDefinition.OrderBy.Add(order); - } + source.WindowDefinition.AddOrder(order); + } - public static void AddOrder(this OverClause source, Func orderbuilder) - { + public static void AddOrder(this NamedWindowDefinition source, Func orderbuilder) + { source.WindowDefinition ??= new(); - source.WindowDefinition.OrderBy ??= new(); - source.WindowDefinition.OrderBy.Add(orderbuilder()); - } + source.WindowDefinition.AddOrder(orderbuilder()); + } } diff --git a/src/Carbunql/Clauses/NamedWindowDefinition.cs b/src/Carbunql/Clauses/NamedWindowDefinition.cs index d4c3be0f..52c627b5 100644 --- a/src/Carbunql/Clauses/NamedWindowDefinition.cs +++ b/src/Carbunql/Clauses/NamedWindowDefinition.cs @@ -12,6 +12,12 @@ public NamedWindowDefinition() WindowDefinition = null!; } + public NamedWindowDefinition(string alias) + { + Alias = alias; + WindowDefinition = null!; + } + public NamedWindowDefinition(string alias, WindowDefinition definition) { Alias = alias; diff --git a/src/Carbunql/Clauses/OverClause.cs b/src/Carbunql/Clauses/OverClause.cs index 60850264..77fe02dd 100644 --- a/src/Carbunql/Clauses/OverClause.cs +++ b/src/Carbunql/Clauses/OverClause.cs @@ -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 GetCommonTables() diff --git a/test/Carbunql.Building.Test/WindowTest.cs b/test/Carbunql.Building.Test/WindowTest.cs new file mode 100644 index 00000000..cf74d7f5 --- /dev/null +++ b/test/Carbunql.Building.Test/WindowTest.cs @@ -0,0 +1,84 @@ +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.AddPartition(new ColumnValue(a, "name")); + w.AddOrder(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); + } +} \ No newline at end of file From 808a7b0f990e48fbb85afc9bd822acd4e458a4f8 Mon Sep 17 00:00:00 2001 From: mk3008 Date: Wed, 31 Jan 2024 22:48:09 +0900 Subject: [PATCH 2/2] Created a sense of unity in function names. AddPartiton function has been changed to Partition function. The AddOrder function has been changed to the Order function. This is because the description of the Order clause is an Order function. --- .../Building/WindowFunctionExtension.cs | 64 +++++++++---------- test/Carbunql.Building.Test/FunctionTest.cs | 4 +- .../SerializeTest.ValueBase.cs | 4 +- test/Carbunql.Building.Test/WindowTest.cs | 31 ++++++++- 4 files changed, 65 insertions(+), 38 deletions(-) diff --git a/src/Carbunql/Building/WindowFunctionExtension.cs b/src/Carbunql/Building/WindowFunctionExtension.cs index 337db3c7..a9954df6 100644 --- a/src/Carbunql/Building/WindowFunctionExtension.cs +++ b/src/Carbunql/Building/WindowFunctionExtension.cs @@ -5,117 +5,117 @@ namespace Carbunql.Building; public static class WindowFunctionExtension { - public static void AddPartition(this OverClause source, ValueBase partition) + public static void Partition(this OverClause source, ValueBase partition) { source.WindowDefinition ??= new(); - source.WindowDefinition.AddPartition(partition); + source.WindowDefinition.Partition(partition); } - public static void AddPartition(this OverClause source, Func partitionbuilder) + public static void Partition(this OverClause source, Func partitionbuilder) { source.WindowDefinition ??= new(); - source.WindowDefinition.AddPartition(partitionbuilder()); + source.WindowDefinition.Partition(partitionbuilder()); } - public static void AddPartition(this OverClause source, SelectableItem order) + public static void Partition(this OverClause source, SelectableItem order) { source.WindowDefinition ??= new(); - source.WindowDefinition.AddPartition(order.Value); + source.WindowDefinition.Partition(order.Value); } - public static void AddOrder(this OverClause source, ColumnValue order) + public static void Order(this OverClause source, ColumnValue order) { source.WindowDefinition ??= new(); - source.WindowDefinition.AddOrder(order.ToSortable()); + source.WindowDefinition.Order(order.ToSortable()); } - public static void AddOrder(this OverClause source, SortableItem order) + public static void Order(this OverClause source, SortableItem order) { source.WindowDefinition ??= new(); - source.WindowDefinition.AddOrder(order); + source.WindowDefinition.Order(order); } - public static void AddOrder(this OverClause source, Func orderbuilder) + public static void Order(this OverClause source, Func orderbuilder) { source.WindowDefinition ??= new(); - source.WindowDefinition.AddOrder(orderbuilder()); + source.WindowDefinition.Order(orderbuilder()); } - public static void AddPartition(this WindowDefinition source, ValueBase partition) + public static void Partition(this WindowDefinition source, ValueBase partition) { source.PartitionBy ??= new(); source.PartitionBy.Add(partition); } - public static void AddPartition(this WindowDefinition source, Func partitionbuilder) + public static void Partition(this WindowDefinition source, Func partitionbuilder) { source.PartitionBy ??= new(); source.PartitionBy.Add(partitionbuilder()); } - public static void AddPartition(this WindowDefinition source, SelectableItem order) + public static void Partition(this WindowDefinition source, SelectableItem order) { source.PartitionBy ??= new(); source.PartitionBy.Add(order.Value); } - public static void AddOrder(this WindowDefinition source, ColumnValue order) + public static void Order(this WindowDefinition source, ColumnValue order) { source.OrderBy ??= new(); source.OrderBy.Add(order.ToSortable()); } - public static void AddOrder(this WindowDefinition source, SortableItem order) + public static void Order(this WindowDefinition source, SortableItem order) { source.OrderBy ??= new(); source.OrderBy.Add(order); } - public static void AddOrder(this WindowDefinition source, Func orderbuilder) + public static void Order(this WindowDefinition source, Func orderbuilder) { source.OrderBy ??= new(); source.OrderBy.Add(orderbuilder()); } - public static void AddPartition(this NamedWindowDefinition source, ValueBase partition) + public static void Partition(this NamedWindowDefinition source, ValueBase partition) { source.WindowDefinition ??= new(); - source.WindowDefinition.AddPartition(partition); + source.WindowDefinition.Partition(partition); } - public static void AddPartition(this NamedWindowDefinition source, Func partitionbuilder) + public static void Partition(this NamedWindowDefinition source, Func partitionbuilder) { source.WindowDefinition ??= new(); - source.WindowDefinition.AddPartition(partitionbuilder()); + source.WindowDefinition.Partition(partitionbuilder()); } - public static void AddPartition(this NamedWindowDefinition source, SelectableItem order) + public static void Partition(this NamedWindowDefinition source, SelectableItem order) { source.WindowDefinition ??= new(); - source.WindowDefinition.AddPartition(order.Value); + source.WindowDefinition.Partition(order.Value); } - public static void AddOrder(this NamedWindowDefinition source, ColumnValue order) + public static void Order(this NamedWindowDefinition source, ColumnValue order) { source.WindowDefinition ??= new(); - source.WindowDefinition.AddOrder(order.ToSortable()); + source.WindowDefinition.Order(order.ToSortable()); } - public static void AddOrder(this NamedWindowDefinition source, SelectableItem order) + public static void Order(this NamedWindowDefinition source, SelectableItem order) { source.WindowDefinition ??= new(); - source.WindowDefinition.AddOrder(order.Value.ToSortable()); + source.WindowDefinition.Order(order.Value.ToSortable()); } - public static void AddOrder(this NamedWindowDefinition source, SortableItem order) + public static void Order(this NamedWindowDefinition source, SortableItem order) { source.WindowDefinition ??= new(); - source.WindowDefinition.AddOrder(order); + source.WindowDefinition.Order(order); } - public static void AddOrder(this NamedWindowDefinition source, Func orderbuilder) + public static void Order(this NamedWindowDefinition source, Func orderbuilder) { source.WindowDefinition ??= new(); - source.WindowDefinition.AddOrder(orderbuilder()); + source.WindowDefinition.Order(orderbuilder()); } } diff --git a/test/Carbunql.Building.Test/FunctionTest.cs b/test/Carbunql.Building.Test/FunctionTest.cs index 4e3cc101..528b8e02 100644 --- a/test/Carbunql.Building.Test/FunctionTest.cs +++ b/test/Carbunql.Building.Test/FunctionTest.cs @@ -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"); diff --git a/test/Carbunql.Building.Test/SerializeTest.ValueBase.cs b/test/Carbunql.Building.Test/SerializeTest.ValueBase.cs index b1bde723..36c42f05 100644 --- a/test/Carbunql.Building.Test/SerializeTest.ValueBase.cs +++ b/test/Carbunql.Building.Test/SerializeTest.ValueBase.cs @@ -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); diff --git a/test/Carbunql.Building.Test/WindowTest.cs b/test/Carbunql.Building.Test/WindowTest.cs index cf74d7f5..4be9fe47 100644 --- a/test/Carbunql.Building.Test/WindowTest.cs +++ b/test/Carbunql.Building.Test/WindowTest.cs @@ -58,8 +58,8 @@ public void NamedWindow() var (_, a) = sq.From("table_a").As("a"); var w = new NamedWindowDefinition("w1"); - w.AddPartition(new ColumnValue(a, "name")); - w.AddOrder(new ColumnValue(a, "a_id")); + w.Partition(new ColumnValue(a, "name")); + w.Order(new ColumnValue(a, "a_id")); sq.Window(w); @@ -81,4 +81,31 @@ ORDER BY 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); + } } \ No newline at end of file