protected override Expression VisitSelect(SelectExpression select)
 {
     Visit(select.Where);
     VisitOrderBy(select.OrderBy);
     VisitFieldDeclarationList(select.Fields);
     return select;
 }
 protected override Expression VisitSelect(SelectExpression select)
 {
     var newAlias = new Alias();
     _map[select.Alias] = newAlias;
     select = (SelectExpression)base.VisitSelect(select);
     return new SelectExpression(newAlias, select.Fields, select.From, select.Where, select.OrderBy, select.GroupBy, select.IsDistinct, select.Skip, select.Take);
 }
 public ProjectionExpression(SelectExpression source, Expression projector, LambdaExpression aggregator)
     : base(MongoExpressionType.Projection, aggregator != null ? aggregator.Body.Type : typeof(IEnumerable<>).MakeGenericType(projector.Type))
 {
     Source = source;
     Projector = projector;
     Aggregator = aggregator;
 }
        protected override Expression VisitSelect(SelectExpression select)
        {
            var saveIsOuterMostSelect = _isOutermostSelect;
            try
            {
                _isOutermostSelect = false;
                select = (SelectExpression)base.VisitSelect(select);

                var hasOrderBy = select.OrderBy != null && select.OrderBy.Count > 0;
                var hasGroupBy = select.GroupBy != null;
                var canHaveOrderings = saveIsOuterMostSelect || select.Take != null || select.Skip != null;
                var canReceivedOrderings = canHaveOrderings && !hasGroupBy && !select.IsDistinct;

                if (hasOrderBy)
                    PrependOrderings(select.OrderBy);

                IEnumerable<OrderExpression> orderings = null;
                if (canReceivedOrderings)
                    orderings = _gatheredOrderings;
                else if (canHaveOrderings)
                    orderings = select.OrderBy;

                var canPassOnOrderings = !saveIsOuterMostSelect && !hasGroupBy && !select.IsDistinct;
                ReadOnlyCollection<FieldDeclaration> fields = select.Fields;
                if (_gatheredOrderings != null)
                {
                    if (canPassOnOrderings)
                    {
                        var producedAliases = new DeclaredAliasGatherer().Gather(select.From);

                        BindResult project = RebindOrderings(_gatheredOrderings, select.Alias, producedAliases, select.Fields);
                        _gatheredOrderings = null;
                        PrependOrderings(project.Orderings);
                        fields = project.Fields;
                    }
                    else
                        _gatheredOrderings = null;
                }
                if (orderings != select.OrderBy || fields != select.Fields)
                    select = new SelectExpression(select.Alias, fields, select.From, select.Where, orderings, select.GroupBy, select.IsDistinct, select.Skip, select.Take);

                return select;
            }
            finally
            {
                _isOutermostSelect = saveIsOuterMostSelect;
            }
        }
 protected override Expression VisitSelect(SelectExpression select)
 {
     select = (SelectExpression)base.VisitSelect(select);
     if (_lookup.Contains(select.Alias))
     {
         var fields = new List<FieldDeclaration>(select.Fields);
         foreach (var ae in _lookup[select.Alias])
         {
             var name = "_$agg" + fields.Count;
             var field = new FieldDeclaration(name, ae.AggregateInGroupSelect);
             if (_map.ContainsKey(ae))
                 continue;
             _map.Add(ae, new FieldExpression(ae.AggregateInGroupSelect, ae.GroupByAlias, name));
             fields.Add(field);
         }
         return new SelectExpression(select.Alias, fields, select.From, select.Where, select.OrderBy, select.GroupBy, select.IsDistinct, select.Skip, select.Take);
     }
     return select;
 }
        protected override Expression VisitSelect(SelectExpression select)
        {
            bool wasTopLevel = _isTopLevel;
            _isTopLevel = false;

            select = (SelectExpression)base.VisitSelect(select);

            while (CanMergeWithFrom(select, wasTopLevel))
            {
                var fromSelect = (SelectExpression)select.From;

                select = (SelectExpression)new SubqueryRemover().Remove(select, new[] { fromSelect });
                   
                var where = select.Where;
                if(fromSelect.Where != null)
                {
                    if (where != null)
                        where = Expression.And(fromSelect.Where, where);
                    else
                        where = fromSelect.Where;
                }

                var groupBy = select.GroupBy ?? fromSelect.GroupBy;
                var orderBy = select.OrderBy != null && select.OrderBy.Count > 0 ? select.OrderBy : fromSelect.OrderBy;
                var skip = select.Skip ?? fromSelect.Skip;
                var take = select.Take ?? fromSelect.Take;
                bool distinct = select.IsDistinct | fromSelect.IsDistinct;
                var fields = select.Fields.Count > 0 ? select.Fields : fromSelect.Fields;

                if (where != select.Where
                    || orderBy != select.OrderBy
                    || groupBy != select.GroupBy
                    || distinct != select.IsDistinct
                    || skip != select.Skip
                    || take != select.Take
                    || fields != select.Fields)
                {
                    select = new SelectExpression(select.Alias, fields, select.From, where, orderBy, groupBy, distinct, skip, take);
                }
            }

            return select;
        }
        private static bool CanMergeWithFrom(SelectExpression select, bool isTopLevel)
        {
            var fromSelect = select.From as SelectExpression;
            if (fromSelect == null)
                return false;

            var fromIsSimpleProjection = IsSimpleProjection(fromSelect);
            var fromIsNameMapProjection = IsNameMapProjection(fromSelect);
            if (!fromIsSimpleProjection && !fromIsNameMapProjection)
                return false;

            var selectIsNameMapProjection = IsNameMapProjection(select);
            var selectHasOrderBy = select.OrderBy != null && select.OrderBy.Count > 0;
            var selectHasGroupBy = select.GroupBy != null;
            var selectHasAggregates = new AggregateChecker().HasAggregates(select);
            var fromHasOrderBy = fromSelect.OrderBy != null && fromSelect.OrderBy.Count > 0;
            var fromHasGroupBy = fromSelect.GroupBy != null;

            if (selectHasOrderBy && fromHasOrderBy)
                return false;

            if (selectHasGroupBy && fromHasGroupBy)
                return false;

            if(fromHasOrderBy && (selectHasGroupBy || selectHasAggregates || select.IsDistinct))
                return false;

            if(fromHasGroupBy && select.Where != null)
                return false;

            if(fromSelect.Take != null && (select.Take != null || select.Skip != null || select.IsDistinct || selectHasAggregates || selectHasGroupBy))
                return false;

            if(fromSelect.Skip != null && (select.Skip != null || select.IsDistinct || selectHasAggregates || selectHasGroupBy))
                return false;

            if (fromSelect.IsDistinct && (select.Take != null || select.Skip != null || !selectIsNameMapProjection || selectHasGroupBy || selectHasAggregates || (selectHasOrderBy && !isTopLevel)))
                return false;

            return true;
        }
        protected override Expression VisitSelect(SelectExpression select)
        {
            select = (SelectExpression)base.VisitSelect(select);

            var fields = select.Fields.OrderBy(f => f.Name).ToList();
            var removed = new BitArray(fields.Count);
            var anyRemoved = false;
            for (int i = 0, n = fields.Count; i < n; i++)
            {
                var fi = fields[i];
                var fxi = new FieldExpression(fi.Expression, select.Alias, fi.Name);
                for (int j = i + 1; j < n; j++)
                {
                    if (!removed.Get(i))
                    {
                        FieldDeclaration fj = fields[j];
                        if (AreSameExpression(fi.Expression, fj.Expression))
                        {
                            var fxj = new FieldExpression(fj.Expression, select.Alias, fj.Name);
                            _map.Add(fxj, fxi);
                            removed.Set(j, true);
                            anyRemoved = true;
                        }
                    }
                }
            }

            if (anyRemoved)
            {
                var newFields = new List<FieldDeclaration>();
                for (int i = 0, n = fields.Count; i < n; i++)
                {
                    if (!removed.Get(i))
                        newFields.Add(fields[i]);
                }
                select = select.SetFields(newFields);
            }
            return select;
        }
        protected virtual bool CompareSelect(SelectExpression a, SelectExpression b)
        {
            var save = _aliasScope;
            try
            {
                if (!Compare(a.From, b.From))
                    return false;

                _aliasScope = new ScopedDictionary<Alias, Alias>(save);
                MapAliases(a.From, b.From);

                return Compare(a.Where, b.Where)
                    && CompareOrderList(a.OrderBy, b.OrderBy)
                    && Compare(a.GroupBy, b.GroupBy)
                    && Compare(a.Skip, b.Skip)
                    && Compare(a.Take, b.Take)
                    && a.IsDistinct == b.IsDistinct
                    && CompareFieldDeclarations(a.Fields, b.Fields);
            }
            finally
            {
                _aliasScope = save;
            }
        }
 public ScalarExpression(Type type, SelectExpression select)
     : base(MongoExpressionType.Scalar, type, select)
 { }
 protected virtual Expression VisitSelect(SelectExpression select)
 {
     var from = VisitSource(select.From);
     var where = Visit(select.Where);
     var groupBy = Visit(select.GroupBy);
     var orderBy = VisitOrderBy(select.OrderBy);
     var skip = Visit(select.Skip);
     var take = Visit(select.Take);
     var fields = VisitFieldDeclarationList(select.Fields);
     if (from != select.From || where != select.Where || orderBy != select.OrderBy || groupBy != select.GroupBy || skip != select.Skip || take != select.Take || fields != select.Fields)
         return new SelectExpression(select.Alias, fields, from, where, orderBy, groupBy, select.IsDistinct, skip, take);
     return select;
 }
        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;
        }
Beispiel #13
0
 public ProjectionExpression(SelectExpression source, Expression projector)
     : this(source, projector, null)
 {
 }
 protected SubqueryExpression(MongoExpressionType nodeType, Type type, SelectExpression select)
     : base(nodeType, type)
 {
     Select = select;
 }
 protected override Expression VisitSelect(SelectExpression select)
 {
     _aliases.Add(select.Alias);
     return select;
 }
 protected override Expression VisitSelect(SelectExpression select)
 {
     VisitFieldDeclarationList(select.Fields);
     return select;
 }
 protected override Expression VisitSelect(SelectExpression s)
 {
     return _selectsToRemove.Contains(s) ? Visit(s.From) : base.VisitSelect(s);
 }
 protected SubqueryExpression(MongoExpressionType nodeType, Type type, SelectExpression select)
     : base(nodeType, type)
 {
     Select = select;
 }
 public Expression Remove(SelectExpression outerSelect, IEnumerable<SelectExpression> selectsToRemove)
 {
     _selectsToRemove = new HashSet<SelectExpression>(selectsToRemove);
     return Visit(outerSelect);
 }
 private static bool IsUniqueName(SelectExpression select, string name)
 {
     return select.Fields.All(field => field.Name != name);
 }
 public ProjectionExpression(SelectExpression source, Expression projector)
     : this(source, projector, null)
 { }
 private static bool IsSimpleProjection(SelectExpression select)
 {
     return select.Fields.All(field => !string.IsNullOrEmpty(field.Name));
 }
        private static bool IsNameMapProjection(SelectExpression select)
        {
            var fromSelect = select.From as SelectExpression;
            if (select.Fields.Count == 0)
                return true;

            if (fromSelect == null || select.Fields.Count != fromSelect.Fields.Count)
                return false;

            for (int i = 0, n = select.Fields.Count; i < n; i++)
            {
                if (select.Fields[i].Name != fromSelect.Fields[i].Name)
                    return false;
            }

            return true;
        }