internal static List <SqlSelectExpression> Find(Expression source)
        {
            var gatherer = new RedundantSubqueryFinder();

            gatherer.Visit(source);

            return(gatherer.redundant);
        }
        internal static List<SqlSelectExpression> Find(Expression source)
        {
            var gatherer = new RedundantSubqueryFinder();

            gatherer.Visit(source);

            return gatherer.redundant;
        }
        protected override Expression VisitSelect(SqlSelectExpression select)
        {
            select = (SqlSelectExpression)base.VisitSelect(select);

            // Expand all purely redundant subqueries

            var redundantQueries = RedundantSubqueryFinder.Find(select.From);

            if (redundantQueries != null)
            {
                select = SubqueryRemover.Remove(select, redundantQueries);
            }

            return(select);
        }
        protected override Expression VisitProjection(SqlProjectionExpression projection)
        {
            projection = (SqlProjectionExpression)base.VisitProjection(projection);

            if (projection.Select.From is SqlSelectExpression)
            {
                var redundantQueries = RedundantSubqueryFinder.Find(projection.Select);

                if (redundantQueries != null)
                {
                    projection = SubqueryRemover.Remove(projection, redundantQueries);
                }
            }

            return(projection);
        }
            private static bool CanMergeWithFrom(SqlSelectExpression select)
            {
                var fromSelect = GetLeftMostSelect(select.From);

                if (fromSelect == null)
                {
                    return(false);
                }

                if (!IsColumnProjection(fromSelect))
                {
                    return(false);
                }

                var selHasNameMapProjection = RedundantSubqueryFinder.IsNameMapProjection(select);
                var selHasSkip       = select.Skip != null;
                var selHasWhere      = select.Where != null;
                var selHasOrderBy    = select.OrderBy != null && select.OrderBy.Count > 0;
                var selHasGroupBy    = select.GroupBy != null && select.GroupBy.Count > 0;
                var selHasAggregates = SqlAggregateChecker.HasAggregates(select);
                var frmHasOrderBy    = fromSelect.OrderBy != null && fromSelect.OrderBy.Count > 0;
                var frmHasGroupBy    = fromSelect.GroupBy != null && fromSelect.GroupBy.Count > 0;

                // Both cannot have OrderBy
                if (selHasOrderBy && frmHasOrderBy)
                {
                    return(false);
                }

                // Both cannot have GroupBy
                if (selHasGroupBy && frmHasGroupBy)
                {
                    return(false);
                }

                // Cannot move forward OrderBy if outer has GroupBy
                if (frmHasOrderBy && (selHasGroupBy || selHasAggregates || select.Distinct))
                {
                    return(false);
                }

                // Cannot move forward GroupBy if outer has a where clause
                if (frmHasGroupBy && (select.Where != null))
                {
                    return(false);
                }

                // Cannot move forward a take if outer has take or skip or distinct
                if (fromSelect.Take != null && (select.Take != null || selHasSkip || select.Distinct || selHasAggregates || selHasGroupBy))
                {
                    return(false);
                }

                // Cannot move forward a skip if outer has skip or distinct or aggregates with accompanying groupby or where
                if (fromSelect.Skip != null && ((selHasWhere || selHasGroupBy) && (select.Skip != null || select.Distinct || selHasAggregates)))
                {
                    return(false);
                }

                // Cannot merge a distinct if the outer has a distinct or aggregates with accompanying groupby or where
                if (fromSelect.Distinct && (!selHasNameMapProjection || (((selHasWhere || selHasGroupBy) && (selHasAggregates || selHasOrderBy)))))
                {
                    return(false);
                }

                return(true);
            }