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);
        }
Пример #2
0
        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");
        }
Пример #3
0
        static Expression BuildAggregateExpression(Expression collection, AggregateToken at, BuildExpressionContext context)
        {
            Type groupType = collection.Type.GetGenericInterfaces(typeof(IEnumerable <>)).SingleEx(() => "IEnumerable<T> implementations on {0}".FormatWith(collection.Type)).GetGenericArguments()[0];

            if (at.AggregateFunction == Signum.Entities.DynamicQuery.AggregateFunction.Count)
            {
                return(Expression.Call(typeof(Enumerable), "Count", new[] { groupType }, new[] { collection }));
            }

            var body = at.Parent.BuildExpression(context);

            var type = at.Type;

            if (body.Type != type)
            {
                body = body.TryConvert(type);
            }

            var lambda = Expression.Lambda(body, context.Parameter);

            if (at.AggregateFunction == Signum.Entities.DynamicQuery.AggregateFunction.Min || at.AggregateFunction == Signum.Entities.DynamicQuery.AggregateFunction.Max)
            {
                return(Expression.Call(typeof(Enumerable), at.AggregateFunction.ToString(), new[] { groupType, lambda.Body.Type }, new[] { collection, lambda }));
            }

            return(Expression.Call(typeof(Enumerable), at.AggregateFunction.ToString(), new[] { groupType }, new[] { collection, lambda }));
        }
Пример #4
0
        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");
        }
Пример #5
0
        private AggregateTransformationNode BindAggregateToken(AggregateToken token)
        {
            var statements = new List<AggregateStatement>();
            foreach (var statementToken in token.Statements)
            {
                statements.Add(BindAggregateStatementToken(statementToken));
            }

            return new AggregateTransformationNode(statements);
        }
Пример #6
0
        private AggregateTransformationNode BindAggregateToken(AggregateToken token)
        {
            var statements = new List <AggregateStatement>();

            foreach (var statementToken in token.Statements)
            {
                statements.Add(BindAggregateStatementToken(statementToken));
            }

            return(new AggregateTransformationNode(statements));
        }
Пример #7
0
        public void ParseApplyWithSingleAggregateExpressionShouldReturnAggregateToken()
        {
            string apply = "aggregate(UnitPrice with sum as TotalPrice)";

            IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply);

            Assert.NotNull(actual);
            var token = Assert.Single(actual);

            AggregateToken aggregate     = Assert.IsType <AggregateToken>(token);
            var            aggregateExpr = Assert.Single(aggregate.AggregateExpressions);

            VerifyAggregateExpressionToken("UnitPrice", AggregationMethodDefinition.Sum, "TotalPrice", aggregateExpr as AggregateExpressionToken);
        }
        public void ParseApplyWithDottedUnkownExpressionShouldReturnCustomAggregateToken()
        {
            string apply = "aggregate(UnitPrice with Custom.Aggregate as CustomAggregate)";

            IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply);

            actual.Should().NotBeNull();
            actual.Should().HaveCount(1);

            AggregateToken aggregate = actual.First() as AggregateToken;

            aggregate.Should().NotBeNull();
            aggregate.AggregateExpressions.Should().HaveCount(1);

            VerifyAggregateExpressionToken("UnitPrice", AggregationMethodDefinition.Custom("Custom.Aggregate"), "CustomAggregate", aggregate.AggregateExpressions.First() as AggregateExpressionToken);
        }
Пример #9
0
        public void NestedAggregateTransformationIsAllowed()
        {
            var result = this.ParseExpandOptions("($apply=aggregate(Amount with sum as Total))");

            result.Should().NotBeNull();

            QueryToken token = result.ApplyOptions.Single();

            token.Should().BeOfType <AggregateToken>();
            AggregateToken           aggregate = token as AggregateToken;
            AggregateExpressionToken aggregateExpressionToken = aggregate.Expressions.Single();

            aggregateExpressionToken.Alias.Should().Equals("Total");
            aggregateExpressionToken.Method.Should().Equals(AggregationMethod.Sum);
            aggregateExpressionToken.Expression.ShouldBeEndPathToken("Amount");
        }
        public void ParseApplyWithSingleCountExpressionShouldReturnAggregateToken()
        {
            string apply = "aggregate($count as Count)";

            IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply);

            actual.Should().NotBeNull();
            actual.Should().HaveCount(1);

            AggregateToken aggregate = actual.First() as AggregateToken;

            aggregate.Should().NotBeNull();
            aggregate.AggregateExpressions.Should().HaveCount(1);

            VerifyAggregateExpressionToken("$count", AggregationMethodDefinition.VirtualPropertyCount, "Count", aggregate.AggregateExpressions.First() as AggregateExpressionToken);
        }
        public void ParseApplyWithSingleAggregateExpressionShouldReturnAggregateToken()
        {
            string apply = "aggregate(UnitPrice with sum as TotalPrice)";

            IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply);

            actual.Should().NotBeNull();
            actual.Should().HaveCount(1);

            AggregateToken aggregate = actual.First() as AggregateToken;

            aggregate.Should().NotBeNull();
            aggregate.AggregateExpressions.Should().HaveCount(1);

            VerifyAggregateExpressionToken("UnitPrice", AggregationMethodDefinition.Sum, "TotalPrice", aggregate.AggregateExpressions.First() as AggregateExpressionToken);
        }
Пример #12
0
        public void NestedAggregateTransformationInExpandIsAllowed()
        {
            // Arrange & Act
            ExpandTermToken expandTerm = this.ParseExpandOptions("($apply=aggregate(Amount with sum as Total))");

            // Assert
            Assert.NotNull(expandTerm);
            Assert.NotNull(expandTerm.ApplyOptions);

            QueryToken               token     = Assert.Single(expandTerm.ApplyOptions);
            AggregateToken           aggregate = Assert.IsType <AggregateToken>(token);
            AggregateExpressionToken aggregateExpressionToken = Assert.Single(aggregate.Expressions);

            Assert.Equal("Total", aggregateExpressionToken.Alias);
            Assert.Equal(AggregationMethod.Sum, aggregateExpressionToken.Method);
            aggregateExpressionToken.Expression.ShouldBeEndPathToken("Amount");
        }
        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 ParseApplyWithMultipleAggregateExpressionsShouldReturnAggregateTokens()
        {
            string apply = "aggregate(CustomerId with sum as Total, SharePrice with countdistinct as SharePriceDistinctCount)";

            IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply);

            actual.Should().NotBeNull();
            actual.Should().HaveCount(1);

            AggregateToken aggregate = actual.First() as AggregateToken;

            aggregate.Should().NotBeNull();
            aggregate.AggregateExpressions.Should().HaveCount(2);

            List <AggregateTokenBase> statements = aggregate.AggregateExpressions.ToList();

            VerifyAggregateExpressionToken("CustomerId", AggregationMethodDefinition.Sum, "Total", statements[0] as AggregateExpressionToken);
            VerifyAggregateExpressionToken("SharePrice", AggregationMethodDefinition.CountDistinct, "SharePriceDistinctCount", statements[1] as AggregateExpressionToken);
        }
Пример #15
0
        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 ParseApplyWithCountAndOtherAggregationExpressionShouldReturnAggregateToken()
        {
            string apply = "aggregate($count as Count, SharePrice with countdistinct as SharePriceDistinctCount)";

            IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply);

            actual.Should().NotBeNull();
            actual.Should().HaveCount(1);

            AggregateToken aggregate = actual.First() as AggregateToken;

            aggregate.Should().NotBeNull();
            aggregate.AggregateExpressions.Should().HaveCount(2);

            List <AggregateTokenBase> statements = aggregate.AggregateExpressions.ToList();

            VerifyAggregateExpressionToken("$count", AggregationMethodDefinition.VirtualPropertyCount, "Count", aggregate.AggregateExpressions.First() as AggregateExpressionToken);
            VerifyAggregateExpressionToken("SharePrice", AggregationMethodDefinition.CountDistinct, "SharePriceDistinctCount", statements[1] as AggregateExpressionToken);
        }
        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);
        }
Пример #19
0
        public void ParseApplyWithExpandFollowedByAggregateShouldParseSuccessfully()
        {
            string apply = "expand(Sales, filter(Amount gt 3))/aggregate($count as Count)";
            IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply);

            Assert.NotNull(actual);
            Assert.Equal(2, actual.Count());

            ExpandToken expand = (ExpandToken)actual.First();

            Assert.Single(expand.ExpandTerms);

            ExpandTermToken expandTerm = expand.ExpandTerms.First();

            Assert.Equal(QueryTokenKind.ExpandTerm, expandTerm.Kind);
            Assert.Equal("Sales", expandTerm.PathToNavigationProp.Identifier);
            Assert.NotNull(expandTerm.FilterOption);

            AggregateToken aggregate = (AggregateToken)actual.Last();

            Assert.Single(aggregate.AggregateExpressions);
        }
        public void ParseApplyWithExpandFollowedByAggregateShouldParseSuccessfully()
        {
            string apply = "expand(Sales, filter(Amount gt 3))/aggregate($count as Count)";
            IEnumerable <QueryToken> actual = this.testSubject.ParseApply(apply);

            actual.Should().NotBeNull();
            actual.Should().HaveCount(2);

            ExpandToken expand = (ExpandToken)actual.First();

            expand.ExpandTerms.Should().HaveCount(1);

            ExpandTermToken expandTerm = expand.ExpandTerms.First();

            expandTerm.Kind.ShouldBeEquivalentTo(QueryTokenKind.ExpandTerm);
            expandTerm.PathToNavigationProp.Identifier.ShouldBeEquivalentTo("Sales");
            expandTerm.FilterOption.Should().NotBeNull();

            AggregateToken aggregate = (AggregateToken)actual.Last();

            aggregate.AggregateExpressions.Should().HaveCount(1);
        }
Пример #21
0
 public void StatementsSetCorrectly()
 {
     var token = new AggregateToken(statements);
     ((object)token.Expressions).Should().Be(statements);
 }
 public bool Visit(AggregateToken tokenIn)
 {
     throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "QueryToken of type '{0}' is not supported.", tokenIn.Kind));
 }
Пример #23
0
        public void StatementsSetCorrectly()
        {
            AggregateToken token = new AggregateToken(statements);

            Assert.Same(statements, token.AggregateExpressions);
        }
Пример #24
0
 public void KindIsSetCorrectly()
 {
     var token = new AggregateToken(statements);
     token.Kind.Should().Be(QueryTokenKind.Aggregate);
 }
Пример #25
0
        public void KindIsSetCorrectly()
        {
            AggregateToken token = new AggregateToken(statements);

            Assert.Equal(QueryTokenKind.Aggregate, token.Kind);
        }
 public Expression Visit(AggregateToken tokenIn)
 {
     throw new NotImplementedException();
 }
Пример #27
0
        public void StatementsSetCorrectly()
        {
            var token = new AggregateToken(statements);

            ((object)token.Expressions).Should().Be(statements);
        }
Пример #28
0
        public void KindIsSetCorrectly()
        {
            var token = new AggregateToken(statements);

            token.Kind.Should().Be(QueryTokenKind.Aggregate);
        }
Пример #29
0
 /// <summary>
 /// Visits an AggregateToken
 /// </summary>
 /// <param name="tokenIn">The AggregateToken to visit</param>
 /// <returns>A T bound to this AggregateToken</returns>
 public virtual T Visit(AggregateToken tokenIn)
 {
     throw new NotImplementedException();
 }