public AggregateSubqueryExpression(Alias groupByAlias, Expression aggregateInGroupSelect, ScalarExpression aggregateAsSubquery) : base(MongoExpressionType.AggregateSubquery, aggregateAsSubquery.Type) { GroupByAlias = groupByAlias; AggregateInGroupSelect = aggregateInGroupSelect; AggregateAsSubquery = aggregateAsSubquery; }
protected virtual Expression VisitScalar(ScalarExpression scalar) { SelectExpression select = (SelectExpression)Visit(scalar.Select); if (select != scalar.Select) { return(new ScalarExpression(scalar.Type, select)); } return(scalar); }
protected virtual Expression VisitAggregateSubquery(AggregateSubqueryExpression aggregateSubquery) { Expression e = Visit(aggregateSubquery.AggregateAsSubquery); ScalarExpression subquery = (ScalarExpression)e; if (subquery != aggregateSubquery.AggregateAsSubquery) { return(new AggregateSubqueryExpression(aggregateSubquery.GroupByAlias, aggregateSubquery.AggregateInGroupSelect, subquery)); } return(aggregateSubquery); }
protected override Expression VisitScalar(ScalarExpression scalar) { return scalar; }
private Expression BindAggregate(Expression source, MethodInfo method, LambdaExpression argument, bool isRoot) { var returnType = method.ReturnType; var aggregateType = GetAggregateType(method.Name); bool hasPredicateArgument = HasPredicateArgument(aggregateType); bool distinct = false; bool argumentWasPredicate = false; var methodCallExpression = source as MethodCallExpression; if (methodCallExpression != null && !hasPredicateArgument && argument == null) { if (methodCallExpression.Method.Name == "Distinct" && methodCallExpression.Arguments.Count == 1 && (methodCallExpression.Method.DeclaringType == typeof(Queryable) || methodCallExpression.Method.DeclaringType == typeof(Enumerable))) { source = methodCallExpression.Arguments[0]; distinct = true; } } if (argument != null && hasPredicateArgument) { source = Expression.Call(typeof(Queryable), "Where", method.GetGenericArguments(), source, argument); argument = null; argumentWasPredicate = true; } var projection = VisitSequence(source); Expression argExpression = null; if (argument != null) { _map[argument.Parameters[0]] = projection.Projector; argExpression = Visit(argument.Body); } else if (!hasPredicateArgument) argExpression = projection.Projector; var alias = new Alias(); Expression aggregateExpression = new AggregateExpression(returnType, aggregateType, argExpression, distinct); var selectType = typeof(IEnumerable<>).MakeGenericType(returnType); string fieldName = "_$agg" + (_aggregateCount++); var select = new SelectExpression(alias, new[] { new FieldDeclaration(fieldName, aggregateExpression) }, projection.Source, null); if (isRoot) { var parameter = Expression.Parameter(selectType, "p"); var lambda = Expression.Lambda(Expression.Call(typeof(Enumerable), "Single", new[] { returnType }, parameter), parameter); return new ProjectionExpression( select, new FieldExpression(aggregateExpression, alias, fieldName), lambda); } var subquery = new ScalarExpression(returnType, select); GroupByInfo info; if (!argumentWasPredicate && _groupByMap.TryGetValue(projection, out info)) { if (argument != null) { _map[argument.Parameters[0]] = info.Element; argExpression = Visit(argument.Body); } else if (!hasPredicateArgument) argExpression = info.Element; aggregateExpression = new AggregateExpression(returnType, aggregateType, argExpression, distinct); if (projection == _currentGroupElement) return aggregateExpression; return new AggregateSubqueryExpression(info.Alias, aggregateExpression, subquery); } return subquery; }
protected virtual bool CompareScalar(ScalarExpression a, ScalarExpression b) { return(Compare(a.Select, b.Select)); }
protected virtual Expression VisitScalar(ScalarExpression scalar) { SelectExpression select = (SelectExpression)Visit(scalar.Select); if (select != scalar.Select) return new ScalarExpression(scalar.Type, select); return scalar; }
protected virtual bool CompareScalar(ScalarExpression a, ScalarExpression b) { return Compare(a.Select, b.Select); }