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) { Visit(select.Where); VisitOrderBy(select.OrderBy); VisitFieldDeclarationList(select.Fields); return select; }
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; } }
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 static bool IsUniqueName(SelectExpression select, string name) { return select.Fields.All(field => field.Name != name); }
private static bool IsSimpleProjection(SelectExpression select) { return select.Fields.All(field => !string.IsNullOrEmpty(field.Name)); }
public ProjectionExpression(SelectExpression source, Expression projector) : this(source, projector, null) { }
public ScalarExpression(Type type, SelectExpression select) : base(MongoExpressionType.Scalar, type, select) { }
protected SubqueryExpression(MongoExpressionType nodeType, Type type, SelectExpression select) : base(nodeType, type) { Select = select; }
protected override Expression VisitSelect(SelectExpression select) { VisitFieldDeclarationList(select.Fields); 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; }
private static bool IsUniqueName(SelectExpression select, string name) { return(select.Fields.All(field => field.Name != name)); }
protected override Expression VisitSelect(SelectExpression select) { _aliases.Add(select.Alias); return select; }
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; }