public DbAggregateSubqueryExpression(DbTableAlias groupByAlias,
                                      Expression aggregateInGroupSelect, DbScalarExpression aggregateAsSubquery)
     : base(DbExpressionType.AggregateSubquery, aggregateAsSubquery.Type)
 {
     _aggregateInGroupSelect = aggregateInGroupSelect;
     _groupByAlias           = groupByAlias;
     _aggregateAsSubquery    = aggregateAsSubquery;
 }
 public DbAggregateSubqueryExpression(DbTableAlias groupByAlias, 
     Expression aggregateInGroupSelect, DbScalarExpression aggregateAsSubquery)
     : base(DbExpressionType.AggregateSubquery, aggregateAsSubquery.Type)
 {
     _aggregateInGroupSelect = aggregateInGroupSelect;
     _groupByAlias = groupByAlias;
     _aggregateAsSubquery = aggregateAsSubquery;
 }
Example #3
0
        protected DbScalarExpression UpdateScalar(DbScalarExpression scalar,
                                                  DbSelectExpression select)
        {
            if (select != scalar.Select)
            {
                return(new DbScalarExpression(scalar.Type, select));
            }

            return(scalar);
        }
Example #4
0
        protected DbAggregateSubqueryExpression UpdateAggregateSubquery(
            DbAggregateSubqueryExpression aggregate, DbScalarExpression subquery)
        {
            if (subquery != aggregate.AggregateAsSubquery)
            {
                return(new DbAggregateSubqueryExpression(aggregate.GroupByAlias,
                                                         aggregate.AggregateInGroupSelect, subquery));
            }

            return(aggregate);
        }
 protected DbAggregateSubqueryExpression UpdateAggregateSubquery(
     DbAggregateSubqueryExpression aggregate, DbScalarExpression subquery)
 {
     if (subquery != aggregate.AggregateAsSubquery)
         return new DbAggregateSubqueryExpression(aggregate.GroupByAlias, 
             aggregate.AggregateInGroupSelect, subquery);
     
     return aggregate;
 }
 protected DbScalarExpression UpdateScalar(DbScalarExpression scalar, 
     DbSelectExpression select)
 {
     if (select != scalar.Select)
         return new DbScalarExpression(scalar.Type, select);
     
     return scalar;
 }
 protected virtual Expression VisitScalar(DbScalarExpression scalar)
 {
     DbSelectExpression select = (DbSelectExpression)Visit(scalar.Select);
     return UpdateScalar(scalar, select);
 }
 protected virtual bool CompareScalar(DbScalarExpression a, DbScalarExpression b)
 {
     return(Compare(a.Select, b.Select));
 }
Example #9
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);
        }
        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;
        }
 protected override Expression VisitScalar(DbScalarExpression subquery)
 {
     this.Write("(");
     this.WriteLine(Indentation.Inner);
     this.Visit(subquery.Select);
     this.WriteLine(Indentation.Same);
     this.Write(")");
     this.Indent(Indentation.Outer);
     return subquery;
 }
 protected virtual bool CompareScalar(DbScalarExpression a, DbScalarExpression b)
 {
     return Compare(a.Select, b.Select);
 }
Example #13
0
        protected virtual Expression VisitAggregateSubquery(DbAggregateSubqueryExpression aggregate)
        {
            DbScalarExpression subquery = (DbScalarExpression)Visit(aggregate.AggregateAsSubquery);

            return(UpdateAggregateSubquery(aggregate, subquery));
        }
Example #14
0
        protected virtual Expression VisitScalar(DbScalarExpression scalar)
        {
            DbSelectExpression select = (DbSelectExpression)Visit(scalar.Select);

            return(UpdateScalar(scalar, select));
        }