public DbAggregateExpression(Type type, DbAggregateType aggType, 
     Expression argument, bool isDistinct)
     : base(DbExpressionType.Aggregate, type)
 {
     _type = aggType;
     _argument = argument;
     _isDistinct = isDistinct;
 }
 public DbAggregateExpression(Type type, DbAggregateType aggType,
                              Expression argument, bool isDistinct)
     : base(DbExpressionType.Aggregate, type)
 {
     _type       = aggType;
     _argument   = argument;
     _isDistinct = isDistinct;
 }
Example #3
0
        protected DbAggregateExpression UpdateAggregate(DbAggregateExpression aggregate, Type type,
                                                        DbAggregateType aggType, Expression arg, bool isDistinct)
        {
            if (type != aggregate.Type || aggType != aggregate.AggregateType ||
                arg != aggregate.Argument || isDistinct != aggregate.IsDistinct)
            {
                return(new DbAggregateExpression(type, aggType, arg, isDistinct));
            }

            return(aggregate);
        }
Example #4
0
        protected virtual string GetAggregateName(DbAggregateType aggregateType)
        {
            switch (aggregateType)
            {
            case DbAggregateType.Count: return("COUNT");

            case DbAggregateType.Min: return("MIN");

            case DbAggregateType.Max: return("MAX");

            case DbAggregateType.Sum: return("SUM");

            case DbAggregateType.Average: return("AVG");

            default: throw new Exception(string.Format("Unknown aggregate type: {0}", aggregateType));
            }
        }
 protected DbAggregateExpression UpdateAggregate(DbAggregateExpression aggregate, Type type, 
     DbAggregateType aggType, Expression arg, bool isDistinct)
 {
     if (type != aggregate.Type || aggType != aggregate.AggregateType || 
         arg != aggregate.Argument || isDistinct != aggregate.IsDistinct)
         return new DbAggregateExpression(type, aggType, arg, isDistinct);
     
     return aggregate;
 }
Example #6
0
        private Expression BindAggregate(Expression source, MethodInfo method, LambdaExpression argument, bool isRoot)
        {
            Type            returnType           = method.ReturnType;
            DbAggregateType aggType              = this.GetAggregateType(method.Name);
            bool            hasPredicateArg      = this.HasPredicateArg(aggType);
            bool            isDistinct           = false;
            bool            argumentWasPredicate = false;
            bool            useAlternateArg      = false;

            // check for distinct
            MethodCallExpression mcs = source as MethodCallExpression;

            if (mcs != null && !hasPredicateArg && argument == null)
            {
                if (mcs.Method.Name == "Distinct" && mcs.Arguments.Count == 1 &&
                    (mcs.Method.DeclaringType == typeof(Queryable) || mcs.Method.DeclaringType == typeof(Enumerable)) &&
                    this.mapping.Language.AllowDistinctInAggregates)
                {
                    source     = mcs.Arguments[0];
                    isDistinct = true;
                }
            }

            if (argument != null && hasPredicateArg)
            {
                // convert query.Count(predicate) into query.Where(predicate).Count()
                source               = Expression.Call(typeof(Queryable), "Where", method.GetGenericArguments(), source, argument);
                argument             = null;
                argumentWasPredicate = true;
            }

            DbProjectionExpression projection = this.VisitSequence(source);

            Expression argExpr = null;

            if (argument != null)
            {
                this.map[argument.Parameters[0]] = projection.Projector;
                argExpr = this.Visit(argument.Body);
            }
            else if (!hasPredicateArg || useAlternateArg)
            {
                argExpr = projection.Projector;
            }

            var                alias   = this.GetNextAlias();
            var                pc      = this.ProjectColumns(projection.Projector, alias, projection.Select.Alias);
            Expression         aggExpr = new DbAggregateExpression(returnType, aggType, argExpr, isDistinct);
            DbSelectExpression select  = new DbSelectExpression(alias, new DbColumnDeclaration[] { new DbColumnDeclaration("", aggExpr) }, projection.Select, null);

            if (isRoot)
            {
                ParameterExpression p     = Expression.Parameter(typeof(IEnumerable <>).MakeGenericType(aggExpr.Type), "p");
                LambdaExpression    gator = Expression.Lambda(Expression.Call(typeof(Enumerable), "Single", new Type[] { returnType }, p), p);
                return(new DbProjectionExpression(select, new DbColumnExpression(returnType, null, alias, ""), gator));
            }

            DbScalarExpression subquery = new DbScalarExpression(returnType, select);

            // if we can find the corresponding group-info we can build a special AggregateSubquery node that will enable us to
            // optimize the aggregate expression later using AggregateRewriter
            GroupByInfo info;

            if (!argumentWasPredicate && this.groupByMap.TryGetValue(projection, out info))
            {
                // use the element expression from the group-by info to rebind the argument so the resulting expression is one that
                // would be legal to add to the columns in the select expression that has the corresponding group-by clause.
                if (argument != null)
                {
                    this.map[argument.Parameters[0]] = info.Element;
                    argExpr = this.Visit(argument.Body);
                }
                else if (!hasPredicateArg || useAlternateArg)
                {
                    argExpr = info.Element;
                }
                aggExpr = new DbAggregateExpression(returnType, aggType, argExpr, isDistinct);

                // check for easy to optimize case.  If the projection that our aggregate is based on is really the 'group' argument from
                // the query.GroupBy(xxx, (key, group) => yyy) method then whatever expression we return here will automatically
                // become part of the select expression that has the group-by clause, so just return the simple aggregate expression.
                if (projection == this.currentGroupElement)
                {
                    return(aggExpr);
                }

                return(new DbAggregateSubqueryExpression(info.Alias, aggExpr, subquery));
            }

            return(subquery);
        }
Example #7
0
 private bool HasPredicateArg(DbAggregateType aggregateType)
 {
     return(aggregateType == DbAggregateType.Count);
 }
 private bool HasPredicateArg(DbAggregateType aggregateType)
 {
     return aggregateType == DbAggregateType.Count;
 }
Example #9
0
 protected virtual bool RequiresAsteriskWhenNoArgument(DbAggregateType aggregateType)
 {
     return(aggregateType == DbAggregateType.Count);
 }
 protected virtual bool RequiresAsteriskWhenNoArgument(DbAggregateType aggregateType)
 {
     return aggregateType == DbAggregateType.Count;
 }
 protected virtual string GetAggregateName(DbAggregateType aggregateType)
 {
     switch (aggregateType)
     {
         case DbAggregateType.Count: return "COUNT";
         case DbAggregateType.Min: return "MIN";
         case DbAggregateType.Max: return "MAX";
         case DbAggregateType.Sum: return "SUM";
         case DbAggregateType.Average: return "AVG";
         default: throw new Exception(string.Format("Unknown aggregate type: {0}", aggregateType));
     }
 }