protected override Expression VisitProjection(ProjectionExpression proj) { proj = (ProjectionExpression)base.VisitProjection(proj); if (proj.Source is SelectExpression select && select.From is QueryExpression) { List <SelectExpression> redundant = RedundantSubqueryGatherer.Gather(proj.Source); if (redundant != null) { proj = SubqueryRemover.Remove(proj, redundant); } } return(proj); }
protected override Expression VisitSelect(SelectExpression select) { select = (SelectExpression)base.VisitSelect(select); // first remove all purely redundant subqueries List <SelectExpression> redundant = RedundantSubqueryGatherer.Gather(select.From); if (redundant != null) { select = SubqueryRemover.Remove(select, redundant); } return(select); }
protected override Expression VisitSelect(SelectExpression select) { bool wasTopLevel = _isTopLevel; _isTopLevel = false; select = (SelectExpression)base.VisitSelect(select); // next attempt to merge subqueries that would have been removed by the above // logic except for the existence of a where clause while (CanMergeWithFrom(select, wasTopLevel)) { SelectExpression fromSelect = GetLeftMostSelect(select.From); // remove the redundant subquery select = SubqueryRemover.Remove(select, fromSelect); // merge where expressions Expression where; Expression having; if (fromSelect.GroupBy != null && fromSelect.GroupBy.Count > 0) { where = fromSelect.Where; having = select.Where; if (fromSelect.Having != null) { having = having != null?Expression.AndAlso(fromSelect.Having, having) : fromSelect.Having; } } else { where = select.Where; if (fromSelect.Where != null) { where = where != null?Expression.AndAlso(fromSelect.Where, where) : fromSelect.Where; } having = null; } var orderBy = select.OrderBy != null && select.OrderBy.Count > 0 ? select.OrderBy : fromSelect.OrderBy; var groupBy = select.GroupBy != null && select.GroupBy.Count > 0 ? select.GroupBy : fromSelect.GroupBy; Expression offset = select.Offset; if (fromSelect.Offset != null) { offset = offset == null ? fromSelect.Offset : Expression.Add(fromSelect.Offset, offset); } Expression limit = select.Limit ?? fromSelect.Limit; if (fromSelect.Limit != null) { limit = limit == null ? fromSelect.Limit : Expression.Call(typeof(Math), nameof(Math.Min), null, fromSelect.Limit, limit); } bool isDistinct = select.IsDistinct | fromSelect.IsDistinct; if (where != select.Where || orderBy != select.OrderBy || groupBy != select.GroupBy || having != select.Having || isDistinct != select.IsDistinct || offset != select.Offset || limit != select.Limit) { select = new SelectExpression( select.Alias, select.Columns, select.From, where, groupBy, having, orderBy, offset, limit, isDistinct ); } } return(select); }