Inheritance: Signum.Engine.Linq.DbExpressionVisitor
 protected internal 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 = (ProjectionExpression)SubqueryRemover.Remove(proj, redundant);
         }
     }
     return(proj);
 }
        protected internal 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 = (SelectExpression)SubqueryRemover.Remove(select, redundant);
            }

            return(select);
        }
            protected internal 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 = (SelectExpression)SubqueryRemover.Remove(select, new[] { fromSelect });

                    // merge where expressions
                    Expression where = select.Where;
                    if (fromSelect.Where != null)
                    {
                        if (where != null)
                        {
                            where = Expression.And(fromSelect.Where, where.UnNullify());
                        }
                        else
                        {
                            where = fromSelect.Where;
                        }
                    }
                    var orderBy = select.OrderBy.Count > 0 ? select.OrderBy : fromSelect.OrderBy;
                    var groupBy = select.GroupBy.Count > 0 ? select.GroupBy : fromSelect.GroupBy;
                    //Expression skip = select.Skip != null ? select.Skip : fromSelect.Skip;
                    Expression top        = select.Top != null ? select.Top : fromSelect.Top;
                    bool       isDistinct = select.IsDistinct | fromSelect.IsDistinct;

                    if (where != select.Where ||
                        orderBy != select.OrderBy ||
                        groupBy != select.GroupBy ||
                        isDistinct != select.IsDistinct
                        //|| skip != select.Skip
                        || top != select.Top)
                    {
                        select = new SelectExpression(select.Alias, isDistinct, top, select.Columns, select.From, where, orderBy, groupBy, select.SelectOptions);
                    }
                }

                return(select);
            }