public void NestedGroupbyTransformationsInExpandIsAllowed() { // Arrange & Act ExpandTermToken expandTerm = this.ParseExpandOptions("($apply=groupby((Customer/CountryRegion,Product/Name),aggregate(Amount with sum as Total)))"); // Assert Assert.NotNull(expandTerm); Assert.NotNull(expandTerm.ApplyOptions); QueryToken token = Assert.Single(expandTerm.ApplyOptions); GroupByToken groupBy = Assert.IsType <GroupByToken>(token); Assert.Equal(2, groupBy.Properties.Count()); QueryToken queryToken = groupBy.Properties.ElementAt(0); EndPathToken pathToken = queryToken.ShouldBeEndPathToken("CountryRegion"); pathToken.NextToken.ShouldBeInnerPathToken("Customer"); queryToken = groupBy.Properties.ElementAt(1); pathToken = queryToken.ShouldBeEndPathToken("Name"); pathToken.NextToken.ShouldBeInnerPathToken("Product"); Assert.NotNull(groupBy.Child); AggregateToken aggregate = Assert.IsType <AggregateToken>(groupBy.Child); AggregateExpressionToken aggregateExpressionToken = Assert.Single(aggregate.Expressions); Assert.Equal("Total", aggregateExpressionToken.Alias); Assert.Equal(AggregationMethod.Sum, aggregateExpressionToken.Method); aggregateExpressionToken.Expression.ShouldBeEndPathToken("Amount"); }
public void NestedGroupbyTransformationsIsAllowed() { var result = this.ParseExpandOptions("($apply=groupby((Customer/CountryRegion,Product/Name),aggregate(Amount with sum as Total)))"); result.Should().NotBeNull(); QueryToken token = result.ApplyOptions.Single(); token.Should().BeOfType <GroupByToken>(); GroupByToken groupBy = token as GroupByToken; groupBy.Properties.Should().HaveCount(2); QueryToken queryToken = groupBy.Properties.ElementAt(0); EndPathToken pathToken = queryToken.ShouldBeEndPathToken("CountryRegion"); pathToken.NextToken.ShouldBeInnerPathToken("Customer"); queryToken = groupBy.Properties.ElementAt(1); pathToken = queryToken.ShouldBeEndPathToken("Name"); pathToken.NextToken.ShouldBeInnerPathToken("Product"); groupBy.Child.Should().NotBeNull(); groupBy.Child.Should().BeOfType <AggregateToken>(); AggregateToken aggregate = groupBy.Child as AggregateToken; AggregateExpressionToken aggregateExpressionToken = aggregate.Expressions.Single(); aggregateExpressionToken.Alias.Should().Equals("Total"); aggregateExpressionToken.Method.Should().Equals(AggregationMethod.Sum); aggregateExpressionToken.Expression.ShouldBeEndPathToken("Amount"); }
public void ParseApplyWithNestedAggregation() { string apply = "groupby((UnitPrice), aggregate(Sales($count as Count)))"; IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply); actual.Should().NotBeNull(); actual.Should().HaveCount(1); List <QueryToken> transformations = actual.ToList(); // verify groupby GroupByToken groupBy = transformations[0] as GroupByToken; groupBy.Should().NotBeNull(); VerifyGroupByTokenProperties(new string[] { "UnitPrice" }, groupBy); groupBy.Properties.Should().HaveCount(1); groupBy.Child.Should().NotBeNull(); AggregateToken groupByAggregate = groupBy.Child as AggregateToken; groupByAggregate.AggregateExpressions.Should().HaveCount(1); EntitySetAggregateToken entitySetAggregate = groupByAggregate.AggregateExpressions.First() as EntitySetAggregateToken; entitySetAggregate.Should().NotBeNull(); entitySetAggregate.EntitySet.ShouldBeEndPathToken("Sales"); VerifyAggregateExpressionToken("$count", AggregationMethodDefinition.VirtualPropertyCount, "Count", entitySetAggregate.Expressions.First() as AggregateExpressionToken); }
public void ParseApplyWithMultipleGroupByPropertiesShouldReturnGroupByToken() { string apply = "groupby((UnitPrice, SharePrice, ReservedPrice))"; IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply); actual.Should().NotBeNull(); actual.Should().HaveCount(1); GroupByToken groupBy = actual.First() as GroupByToken; VerifyGroupByTokenProperties(new string[] { "UnitPrice", "SharePrice", "ReservedPrice" }, groupBy); }
private GroupByTransformationNode BindGroupByToken(GroupByToken token) { var properties = new List <GroupByPropertyNode>(); foreach (var propertyToken in token.Properties) { var bindResult = this.bindMethod(propertyToken); var property = bindResult as SingleValuePropertyAccessNode; if (property != null) { RegisterProperty(properties, ReversePropertyPath(property)); } else { var openProperty = bindResult as SingleValueOpenPropertyAccessNode; if (openProperty != null) { var type = GetTypeReferenceByPropertyName(openProperty.Name); properties.Add(new GroupByPropertyNode(openProperty.Name, openProperty, type)); } else { throw new ODataException( ODataErrorStrings.ApplyBinder_GroupByPropertyNotPropertyAccessValue(propertyToken.Identifier)); } } } TransformationNode aggregate = null; if (token.Child != null) { if (token.Child.Kind == QueryTokenKind.Aggregate) { aggregate = BindAggregateToken((AggregateToken)token.Child); aggregateStatementsCache = ((AggregateTransformationNode)aggregate).Statements; state.AggregatedProperties = aggregateStatementsCache.Select(statement => statement.AsAlias).ToList(); } else { throw new ODataException(ODataErrorStrings.ApplyBinder_UnsupportedGroupByChild(token.Child.Kind)); } } // TODO: Determine source return(new GroupByTransformationNode(properties, aggregate, null)); }
public void ParseApplyWithSingleGroupByPropertyShouldReturnGroupByToken() { string apply = "groupby((UnitPrice))"; IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply); Assert.NotNull(actual); Assert.Single(actual); GroupByToken groupBy = actual.First() as GroupByToken; Assert.NotNull(groupBy); VerifyGroupByTokenProperties(new string[] { "UnitPrice" }, groupBy); }
public void ParseApplyWithNestedFunctionAggregation() { string apply = "groupby((UnitPrice), aggregate(Sales($count as Count, cast(SalesPrice, Edm.Decimal) with average as RetailPrice)))"; IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply); actual.Should().NotBeNull(); actual.Should().HaveCount(1); List <QueryToken> transformations = actual.ToList(); // verify groupby GroupByToken groupBy = transformations[0] as GroupByToken; groupBy.Should().NotBeNull(); VerifyGroupByTokenProperties(new string[] { "UnitPrice" }, groupBy); groupBy.Properties.Should().HaveCount(1); groupBy.Child.Should().NotBeNull(); AggregateToken groupByAggregate = groupBy.Child as AggregateToken; groupByAggregate.AggregateExpressions.Should().HaveCount(1); EntitySetAggregateToken entitySetAggregate = groupByAggregate.AggregateExpressions.First() as EntitySetAggregateToken; entitySetAggregate.Should().NotBeNull(); entitySetAggregate.EntitySet.ShouldBeEndPathToken("Sales"); entitySetAggregate.Expressions.Should().HaveCount(2); VerifyAggregateExpressionToken("$count", AggregationMethodDefinition.VirtualPropertyCount, "Count", entitySetAggregate.Expressions.First() as AggregateExpressionToken); AggregateExpressionToken funcAggregate = entitySetAggregate.Expressions.Last() as AggregateExpressionToken; funcAggregate.Should().NotBeNull(); funcAggregate.Alias.ShouldBeEquivalentTo("RetailPrice"); funcAggregate.Method.Should().Equals(AggregationMethodDefinition.Average); FunctionCallToken funcToken = funcAggregate.Expression as FunctionCallToken; funcToken.Should().NotBeNull(); funcToken.Name.ShouldBeEquivalentTo("cast"); }
public void ParseApplyWithNestedAggregationAndFunction() { string apply = "groupby((UnitPrice), aggregate(Sales($count as Count), cast(SalesPrice, Edm.Decimal) with average as RetailPrice))"; IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply); Assert.NotNull(actual); Assert.Single(actual); List <QueryToken> transformations = actual.ToList(); // verify groupby GroupByToken groupBy = transformations[0] as GroupByToken; Assert.NotNull(groupBy); VerifyGroupByTokenProperties(new string[] { "UnitPrice" }, groupBy); Assert.Single(groupBy.Properties); Assert.NotNull(groupBy.Child); AggregateToken groupByAggregate = groupBy.Child as AggregateToken; Assert.Equal(2, groupByAggregate.AggregateExpressions.Count()); EntitySetAggregateToken entitySetAggregate = groupByAggregate.AggregateExpressions.First() as EntitySetAggregateToken; Assert.NotNull(entitySetAggregate); entitySetAggregate.EntitySet.ShouldBeEndPathToken("Sales"); VerifyAggregateExpressionToken("$count", AggregationMethodDefinition.VirtualPropertyCount, "Count", entitySetAggregate.Expressions.First() as AggregateExpressionToken); AggregateExpressionToken funcAggregate = groupByAggregate.AggregateExpressions.Last() as AggregateExpressionToken; Assert.NotNull(funcAggregate); Assert.Equal("RetailPrice", funcAggregate.Alias); Assert.Equal(AggregationMethod.Average, funcAggregate.Method); FunctionCallToken funcToken = funcAggregate.Expression as FunctionCallToken; Assert.NotNull(funcToken); Assert.Equal("cast", funcToken.Name); }
public void ParseApplyWithMultipleTransformationShouldReturnTransformations() { string apply = "groupby((UnitPrice), aggregate(SalesPrice with average as RetailPrice))/filter(UnitPrice eq 5)/aggregate(CustomerId with sum as Total, SharePrice with countdistinct as SharePriceDistinctCount)"; IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply); actual.Should().NotBeNull(); actual.Should().HaveCount(3); List <QueryToken> transformations = actual.ToList(); // verify groupby GroupByToken groupBy = transformations[0] as GroupByToken; groupBy.Should().NotBeNull(); VerifyGroupByTokenProperties(new string[] { "UnitPrice" }, groupBy); groupBy.Properties.Should().HaveCount(1); groupBy.Child.Should().NotBeNull(); AggregateToken groupByAggregate = groupBy.Child as AggregateToken; groupByAggregate.AggregateExpressions.Should().HaveCount(1); VerifyAggregateExpressionToken("SalesPrice", AggregationMethodDefinition.Average, "RetailPrice", groupByAggregate.AggregateExpressions.First() as AggregateExpressionToken); // verify filter BinaryOperatorToken filter = transformations[1] as BinaryOperatorToken; VerifyBinaryOperatorToken <int>("UnitPrice", BinaryOperatorKind.Equal, 5, filter); // verify aggregate AggregateToken aggregate = transformations[2] as AggregateToken; aggregate.Should().NotBeNull(); aggregate.AggregateExpressions.Should().HaveCount(2); List <AggregateTokenBase> aggregateExpressions = aggregate.AggregateExpressions.ToList(); VerifyAggregateExpressionToken("CustomerId", AggregationMethodDefinition.Sum, "Total", aggregateExpressions[0] as AggregateExpressionToken); VerifyAggregateExpressionToken("SharePrice", AggregationMethodDefinition.CountDistinct, "SharePriceDistinctCount", aggregateExpressions[1] as AggregateExpressionToken); }
public void ParseApplyWithGroupByAndAggregateShouldReturnGroupByToken() { string apply = "groupby((UnitPrice), aggregate(SalesPrice with average as RetailPrice))"; IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply); actual.Should().NotBeNull(); actual.Should().HaveCount(1); GroupByToken groupBy = actual.First() as GroupByToken; VerifyGroupByTokenProperties(new string[] { "UnitPrice" }, groupBy); groupBy.Child.Should().NotBeNull(); AggregateToken aggregate = groupBy.Child as AggregateToken; aggregate.AggregateExpressions.Should().HaveCount(1); VerifyAggregateExpressionToken("SalesPrice", AggregationMethodDefinition.Average, "RetailPrice", aggregate.AggregateExpressions.First() as AggregateExpressionToken); }
private GroupByTransformationNode BindGroupByToken(GroupByToken token) { var properties = new List<GroupByPropertyNode>(); foreach (var propertyToken in token.Properties) { var bindResult = this.bindMethod(propertyToken); var property = bindResult as SingleValuePropertyAccessNode; if (property != null) { RegisterProperty(properties, ReversePropertyPath(property)); } else { var openProperty = bindResult as SingleValueOpenPropertyAccessNode; if (openProperty != null) { var type = GetTypeReferenceByPropertyName(openProperty.Name); properties.Add(new GroupByPropertyNode(openProperty.Name, openProperty, type)); } else { throw new ODataException( ODataErrorStrings.ApplyBinder_GroupByPropertyNotPropertyAccessValue(propertyToken.Identifier)); } } } TransformationNode aggregate = null; if (token.Child != null) { if (token.Child.Kind == QueryTokenKind.Aggregate) { aggregate = BindAggregateToken((AggregateToken)token.Child); aggregateStatementsCache = ((AggregateTransformationNode)aggregate).Statements; state.AggregatedProperties = aggregateStatementsCache.Select(statement => statement.AsAlias).ToList(); } else { throw new ODataException(ODataErrorStrings.ApplyBinder_UnsupportedGroupByChild(token.Child.Kind)); } } // TODO: Determine source return new GroupByTransformationNode(properties, aggregate, null); }
public Expression Visit(GroupByToken tokenIn) { throw new NotImplementedException(); }
/// <summary> /// Visits a GroupByToken /// </summary> /// <param name="tokenIn">The GroupByToken to visit</param> /// <returns>A T bound to this GroupByToken</returns> public virtual T Visit(GroupByToken tokenIn) { throw new NotImplementedException(); }
private static void VerifyGroupByTokenProperties(IEnumerable <string> expectedEndPathIdentifiers, GroupByToken actual) { actual.Should().NotBeNull(); if (expectedEndPathIdentifiers == null || !expectedEndPathIdentifiers.Any()) { actual.Properties.Should().HaveCount(0); } else { actual.Properties.Should().HaveCount(expectedEndPathIdentifiers.Count()); List <string> expectedIdentifierList = expectedEndPathIdentifiers.ToList(); int i = 0; foreach (EndPathToken actualProperty in actual.Properties) { actualProperty.Should().NotBeNull(); EndPathToken endPathToken = actualProperty as EndPathToken; endPathToken.Should().NotBeNull(); endPathToken.Identifier.Should().Be(expectedIdentifierList[i]); i++; } } }
public void AggregateSetCorrectly() { var token = new GroupByToken(properties, aggregate); ((object)token.Child).Should().Be(aggregate); }
public void KindIsSetCorrectly() { var token = new GroupByToken(properties, null); token.Kind.Should().Be(QueryTokenKind.AggregateGroupBy); }
public void KindIsSetCorrectly() { var token = new GroupByToken(properties, null); Assert.Equal(QueryTokenKind.AggregateGroupBy, token.Kind); }
public void PropertiesSetCorrectly() { var token = new GroupByToken(properties, null); ((object)token.Properties).Should().Be(properties); }
public void AggregateSetCorrectly() { var token = new GroupByToken(properties, aggregate); Assert.Same(aggregate, ((object)token.Child)); }
private static void VerifyGroupByTokenProperties(IEnumerable <string> expectedEndPathIdentifiers, GroupByToken actual) { Assert.NotNull(actual); if (expectedEndPathIdentifiers == null || !expectedEndPathIdentifiers.Any()) { Assert.Empty(actual.Properties); } else { Assert.Equal(actual.Properties.Count(), expectedEndPathIdentifiers.Count()); List <string> expectedIdentifierList = expectedEndPathIdentifiers.ToList(); int i = 0; foreach (EndPathToken actualProperty in actual.Properties) { Assert.NotNull(actualProperty); EndPathToken endPathToken = actualProperty as EndPathToken; Assert.NotNull(endPathToken); Assert.Equal(endPathToken.Identifier, expectedIdentifierList[i]); i++; } } }
public void PropertiesSetCorrectly() { var token = new GroupByToken(properties, null); Assert.Same(properties, ((object)token.Properties)); }
public bool Visit(GroupByToken tokenIn) { throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "QueryToken of type '{0}' is not supported.", tokenIn.Kind)); }