From 3a51fa0a3c434c56f243623aa5a766df39996aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Thu, 20 Jun 2024 14:53:21 +0200 Subject: [PATCH] Support type cast in group by (#2879) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix * Tests --------- Co-authored-by: Clément Bernard --- .../UriParser/Aggregation/ApplyBinder.cs | 9 +++- .../Extensions/Binders/ApplyBinderTests.cs | 52 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OData.Core/UriParser/Aggregation/ApplyBinder.cs b/src/Microsoft.OData.Core/UriParser/Aggregation/ApplyBinder.cs index 8b5961ff04..736a6461e5 100644 --- a/src/Microsoft.OData.Core/UriParser/Aggregation/ApplyBinder.cs +++ b/src/Microsoft.OData.Core/UriParser/Aggregation/ApplyBinder.cs @@ -277,7 +277,8 @@ private static bool IsPropertyNode(SingleValueNode node) { return node.Kind == QueryNodeKind.SingleValuePropertyAccess || node.Kind == QueryNodeKind.SingleComplexNode || - node.Kind == QueryNodeKind.SingleNavigationNode; + node.Kind == QueryNodeKind.SingleNavigationNode || + node.Kind == QueryNodeKind.SingleResourceCast; } private static Stack ReversePropertyPath(SingleValueNode node) @@ -285,6 +286,12 @@ private static Stack ReversePropertyPath(SingleValueNode node) Stack result = new Stack(); do { + if (node.Kind == QueryNodeKind.SingleResourceCast) + { + node = ((SingleResourceCastNode)node).Source; + continue; + } + result.Push(node); if (node.Kind == QueryNodeKind.SingleValuePropertyAccess) { diff --git a/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/Extensions/Binders/ApplyBinderTests.cs b/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/Extensions/Binders/ApplyBinderTests.cs index 0a2302cd5a..30dcc3f62f 100644 --- a/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/Extensions/Binders/ApplyBinderTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/Extensions/Binders/ApplyBinderTests.cs @@ -786,6 +786,58 @@ public void BindVirtualPropertiesAfterCollapseReturnsApplyClause() Assert.Equal(AggregationMethod.VirtualPropertyCount, aggExp.Method); } + [Fact] + public void BindApplyWithGroupByAndTypeCastShouldReturnApplyClause() + { + IEnumerable tokens = _parser.ParseApply("groupby((Fully.Qualified.Namespace.Employee/WorkEmail))"); + + MetadataBinder metadataBiner = new MetadataBinder(_bindingState); + + ApplyBinder binder = new ApplyBinder(metadataBiner.Bind, _bindingState); + ApplyClause actual = binder.BindApply(tokens); + + Assert.NotNull(actual); + + var transformation = Assert.Single(actual.Transformations); + GroupByTransformationNode groupBy = Assert.IsType(transformation); + + Assert.Equal(TransformationNodeKind.GroupBy, groupBy.Kind); + Assert.Null(groupBy.ChildTransformations); + Assert.NotNull(groupBy.GroupingProperties); + + GroupByPropertyNode workEmailNode = Assert.Single(groupBy.GroupingProperties); + Assert.NotNull(workEmailNode.Expression); + Assert.Empty(workEmailNode.ChildTransformations); + } + + [Fact] + public void BindApplyWithGroupByComplexAndTypeCastShouldReturnApplyClause() + { + IEnumerable tokens = _parser.ParseApply("groupby((MyAddress/Fully.Qualified.Namespace.HomeAddress/HomeNO))"); + + MetadataBinder metadataBiner = new MetadataBinder(_bindingState); + + ApplyBinder binder = new ApplyBinder(metadataBiner.Bind, _bindingState); + ApplyClause actual = binder.BindApply(tokens); + + Assert.NotNull(actual); + + var transformation = Assert.Single(actual.Transformations); + GroupByTransformationNode groupBy = Assert.IsType(transformation); + + Assert.Equal(TransformationNodeKind.GroupBy, groupBy.Kind); + Assert.Null(groupBy.ChildTransformations); + Assert.NotNull(groupBy.GroupingProperties); + + GroupByPropertyNode addressNode = Assert.Single(groupBy.GroupingProperties); + Assert.Equal("MyAddress", addressNode.Name); + Assert.Null(addressNode.Expression); + + GroupByPropertyNode homeNode = Assert.Single(addressNode.ChildTransformations); + Assert.NotNull(homeNode.Expression); + Assert.Empty(homeNode.ChildTransformations); + } + private static ConstantNode _booleanPrimitiveNode = new ConstantNode(true); private static SingleValueNode BindMethodReturnsBooleanPrimitive(QueryToken token)