コード例 #1
0
 public AggregateSubqueryExpression(IdentifiableAlias groupByAlias, Expression aggregateInGroupSelect, ScalarExpression aggregateAsSubquery)
     : base(DbExpressionType.AggregateSubquery, aggregateAsSubquery.Type)
 {
     this.aggregateInGroupSelect = aggregateInGroupSelect;
     this.groupByAlias = groupByAlias;
     this.aggregateAsSubquery = aggregateAsSubquery;
 }
コード例 #2
0
 protected AggregateSubqueryExpression UpdateAggregateSubquery(AggregateSubqueryExpression aggregate, ScalarExpression subquery)
 {
     if (subquery != aggregate.AggregateAsSubquery)
     {
         return new AggregateSubqueryExpression(aggregate.GroupByAlias, aggregate.AggregateInGroupSelect, subquery);
     }
     return aggregate;
 }
コード例 #3
0
 protected virtual Expression VisitScalar(ScalarExpression scalar)
 {
     var select = (SelectExpression)this.Visit(scalar.Select);
     return this.UpdateScalar(scalar, select);
 }
コード例 #4
0
 protected ScalarExpression UpdateScalar(ScalarExpression scalar, SelectExpression select)
 {
     if (select != scalar.Select)
     {
         return new ScalarExpression(scalar.Type, select);
     }
     return scalar;
 }
コード例 #5
0
ファイル: SqlFormatter.cs プロジェクト: PaybackMan/Cinder
 protected override Expression VisitScalar(ScalarExpression subquery)
 {
     this.Write("(");
     this.WriteLine(Indentation.Inner);
     this.Visit(subquery.Select);
     this.WriteLine(Indentation.Same);
     this.Write(")");
     this.Indent(Indentation.Outer);
     return subquery;
 }
コード例 #6
0
 protected virtual bool CompareScalar(ScalarExpression a, ScalarExpression b)
 {
     return this.Compare(a.Select, b.Select);
 }
コード例 #7
0
ファイル: QueryBinder.cs プロジェクト: PaybackMan/Cinder
        protected virtual Expression BindAggregate(Expression source, string aggName, Type returnType, LambdaExpression argument, bool isRoot)
        {
            bool hasPredicateArg = this.language.AggregateArgumentIsPredicate(aggName);
            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.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", new[] { TypeHelper.GetElementType(source.Type) }, source, argument);
                argument = null;
                argumentWasPredicate = true;
            }

            ProjectionExpression 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();
            Expression aggExpr = new AggregateExpression(returnType, aggName, argExpr, isDistinct);
            var colType = this.language.TypeSystem.GetStorageType(returnType);
            SelectExpression select = new SelectExpression(alias, new FieldDeclaration[] { new FieldDeclaration("", aggExpr, colType) }, 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 ProjectionExpression(select, new FieldExpression(
                    returnType,
                    this.language.TypeSystem.GetStorageType(returnType),
                    alias,
                    ""),
                    gator);
            }

            ScalarExpression subquery = new ScalarExpression(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 fields 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 AggregateExpression(returnType, aggName, 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 AggregateSubqueryExpression(info.Alias, aggExpr, subquery);
            }

            return subquery;
        }