Beispiel #1
0
        internal static bool HasAggregates(SqlSelectExpression expression, bool ignoreInSubqueries)
        {
            var checker = new HasAggregateChecker(ignoreInSubqueries);

            checker.Visit(expression);

            return(checker.hasAggregate);
        }
Beispiel #2
0
        internal static bool HasAggregates(SqlSelectExpression expression, bool ignoreInSubqueries)
        {
            var checker = new HasAggregateChecker(ignoreInSubqueries);

            checker.Visit(expression);

            return checker.hasAggregate;
        }
        protected override Expression VisitSelect(SqlSelectExpression selectExpression)
        {
            if (selectExpression.Columns.Count == 1 &&
                selectExpression.From.NodeType == (ExpressionType)SqlExpressionType.Select &&
                selectExpression.Columns[0].Expression.NodeType == (ExpressionType)SqlExpressionType.Aggregate)
            {
                var from = (SqlSelectExpression)selectExpression.From;
                var aggregateExpression = (SqlAggregateExpression)selectExpression.Columns[0].Expression;

                if (from.Columns.Count > 1 ||
                    aggregateExpression.IsDistinct ||
                    from.Distinct ||
                    from.Take != null ||
                    from.Skip != null ||
                    from.GroupBy != null
                    /* Don't fold a from with an orderby into the outer select if it has a count or other aggregate */
                    || from.OrderBy != null && from.OrderBy.Count > 0 && HasAggregateChecker.HasAggregates(selectExpression))
                {
                    return(base.VisitSelect(selectExpression));
                }

                var newColumns = new List <SqlColumnDeclaration>();

                if (from.Columns.Count == 1)
                {
                    foreach (var column in from.Columns)
                    {
                        if (column.Expression.NodeType != (ExpressionType)SqlExpressionType.Column)
                        {
                            return(base.VisitSelect(selectExpression));
                        }

                        var newAggregate = new SqlAggregateExpression
                                           (
                            aggregateExpression.Type,
                            aggregateExpression.AggregateType,
                            column.Expression,
                            aggregateExpression.IsDistinct
                                           );

                        newColumns.Add(new SqlColumnDeclaration(column.Name, newAggregate));
                    }
                }
                else
                {
                    newColumns.Add(selectExpression.Columns[0]);
                }

                var where = Visit(from.Where);

                return(from.ChangeWhereAndColumns(where, newColumns.ToReadOnlyList(), from.ForUpdate || selectExpression.ForUpdate));
            }

            return(base.VisitSelect(selectExpression));
        }
            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 = HasAggregateChecker.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);
            }