protected override Expression VisitProjection(ProjectionExpression proj)
 {
     proj = (ProjectionExpression)base.VisitProjection(proj);
     if (proj.Select.From is SelectExpression)
     {
         List <SelectExpression> redundant = RedundantSubqueryGatherer.Gather(proj.Select);
         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 = select.Where;
                    if (fromSelect.Where != null)
                    {
                        if (where != null)
                        {
                            where = fromSelect.Where.And(where);
                        }
                        else
                        {
                            where = fromSelect.Where;
                        }
                    }
                    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 skip       = select.Skip != null ? select.Skip : fromSelect.Skip;
                    Expression take       = select.Take != null ? select.Take : fromSelect.Take;
                    bool       isDistinct = select.IsDistinct | fromSelect.IsDistinct;

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

                return(select);
            }