예제 #1
0
        protected override Expression VisitSelect(SqlSelectExpression selectExpression)
        {
            if (selectExpression.Skip != null)
            {
                var rowNumber        = new SqlFunctionCallExpression(typeof(int), "ROW_NUMBER");
                var over             = new SqlOverExpression(rowNumber, selectExpression.OrderBy ?? new ReadOnlyList <Expression>(new [] { new SqlOrderByExpression(OrderType.Ascending, selectExpression.Columns[0].Expression) }));
                var additionalColumn = new SqlColumnDeclaration(RowColumnName, over);

                var newAlias     = selectExpression.Alias + "INNER";
                var innerColumns = new ReadOnlyList <SqlColumnDeclaration>(selectExpression.Columns.Select(c => c).Concat(new[] { additionalColumn }));

                var innerSelect = new SqlSelectExpression(selectExpression.Type, newAlias, innerColumns, selectExpression.From, selectExpression.Where, null, selectExpression.GroupBy, selectExpression.Distinct, null, null, selectExpression.ForUpdate);

                var outerColumns = selectExpression.Columns.Select(c => new SqlColumnDeclaration(c.Name, new SqlColumnExpression(c.Expression.Type, newAlias, c.Name)));

                Expression rowPredicate = Expression.GreaterThan(new SqlColumnExpression(typeof(int), newAlias, additionalColumn.Name), selectExpression.Skip);

                if (selectExpression.Take != null && !(selectExpression.Take is SqlTakeAllValueExpression))
                {
                    rowPredicate = Expression.And
                                   (
                        rowPredicate,
                        Expression.LessThanOrEqual(new SqlColumnExpression(typeof(int), newAlias, additionalColumn.Name), Expression.Add(selectExpression.Skip, selectExpression.Take))
                                   );
                }

                return(new SqlSelectExpression(selectExpression.Type, selectExpression.Alias, outerColumns, innerSelect, rowPredicate, null, selectExpression.ForUpdate));
            }

            return(base.VisitSelect(selectExpression));
        }
예제 #2
0
        protected override Expression VisitSelect(SqlSelectExpression select)
        {
            // Only consider aggregates in these locations

            if (this.hasAggregate)
            {
                return(select);
            }

            this.Visit(select.Where);

            if (this.hasAggregate)
            {
                return(select);
            }

            this.VisitExpressionList(select.OrderBy);

            if (this.hasAggregate)
            {
                return(select);
            }

            this.VisitColumnDeclarations(select.Columns);

            return(select);
        }
예제 #3
0
        protected virtual void AppendLimit(SqlSelectExpression selectExpression)
        {
            if (selectExpression.Skip != null || selectExpression.Take != null)
            {
                this.Write(" LIMIT ");

                if (selectExpression.Skip == null)
                {
                    this.Write("0");
                }
                else
                {
                    this.Visit(selectExpression.Skip);
                }

                if (selectExpression.Take != null)
                {
                    this.Write(", ");

                    this.Visit(selectExpression.Take);
                }
                else if (selectExpression.Skip != null)
                {
                    this.Write(", ");
                    this.Write(Int64.MaxValue);
                }
            }
        }
예제 #4
0
        internal static bool IsNameMapProjection(SqlSelectExpression select)
        {
            if (select.From is SqlTableExpression)
            {
                return(false);
            }

            var fromSelect = select.From as SqlSelectExpression;

            if (fromSelect == null || select.Columns.Count > fromSelect.Columns.Count)
            {
                return(false);
            }

            var fromColumnNames = new HashSet <string>(fromSelect.Columns.Select(x => x.Name));

            foreach (var t in @select.Columns)
            {
                var columnExpression = t.Expression as SqlColumnExpression;

                if (columnExpression == null || !fromColumnNames.Contains(columnExpression.Name))
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #5
0
        protected override void AppendLimit(SqlSelectExpression selectExpression)
        {
            if (selectExpression.Skip != null || selectExpression.Take != null)
            {
                if (selectExpression.Take != null)
                {
                    this.Write(" LIMIT ");

                    this.Visit(selectExpression.Take);

                    this.Write(" ");
                }
                else
                {
                    this.Write(" LIMIT -1 ");
                }

                if (selectExpression.Skip != null)
                {
                    this.Write("OFFSET ");

                    this.Visit(selectExpression.Skip);
                }
            }
        }
예제 #6
0
        protected override Expression VisitSelect(SqlSelectExpression selectExpression)
        {
            var from = selectExpression.From;

            var where = Visit(selectExpression.Where);

            var orderBy = selectExpression.OrderBy;
            var groupBy = selectExpression.GroupBy;
            var skip    = selectExpression.Skip;
            var take    = selectExpression.Take;
            var columns = selectExpression.Columns;

            if (where?.NodeType == ExpressionType.Constant && where.Type == typeof(bool))
            {
                var value = (bool)((ConstantExpression) where).Value;

                if (value)
                {
                    where = null;
                }
            }

            if (where != selectExpression.Where)
            {
                return(new SqlSelectExpression(selectExpression.Type, selectExpression.Alias, columns, from, where, orderBy, groupBy, selectExpression.Distinct, skip, take, selectExpression.ForUpdate));
            }

            return(base.VisitSelect(selectExpression));
        }
 protected override void AppendLimit(SqlSelectExpression selectExpression)
 {
     if (selectExpression.Skip != null && selectExpression.Take != null)
     {
         throw new InvalidOperationException("Skip/Take not supported");
     }
 }
예제 #8
0
        internal static bool HasAggregates(SqlSelectExpression expression, bool ignoreInSubqueries)
        {
            var checker = new HasAggregateChecker(ignoreInSubqueries);

            checker.Visit(expression);

            return(checker.hasAggregate);
        }
예제 #9
0
        protected override Expression VisitUpdate(SqlUpdateExpression expression)
        {
            if (!expression.RequiresIdentityInsert)
            {
                return(base.VisitUpdate(expression));
            }

            var tableName = ((SqlTableExpression)expression.Source).Name;

            var typeDescriptor = this
                                 .typeDescriptorProvider
                                 .GetTypeDescriptors()
                                 .Single(c => c.PersistedName == tableName);

            var insertedColumns = expression
                                  .Assignments
                                  .OfType <SqlAssignExpression>()
                                  .Select(c => new { name = ((SqlColumnExpression)c.Target).Name, value = c.Value, propertyDescriptor = typeDescriptor.GetPropertyDescriptorByColumnName(((SqlColumnExpression)c.Target).Name) })
                                  .ToList();

            var columnInfos = QueryBinder
                              .GetColumnInfos(this.typeDescriptorProvider, typeDescriptor.PersistedProperties.Where(c => insertedColumns.All(d => d.propertyDescriptor != c)))
                              .ToList();

            var visitedUpdated       = (SqlUpdateExpression)base.VisitUpdate(expression);
            var selectIntoExpression = new SqlSelectExpression
                                       (
                typeof(void),
                null,
                columnInfos.Select
                (
                    c => new SqlColumnDeclaration
                    (
                        null, new SqlColumnExpression(c.DefinitionProperty.PropertyType, null, c.GetColumnName())
                    )
                )
                .Concat(insertedColumns.Select(d => d.value.Type.GetUnwrappedNullableType() == typeof(bool) ? new SqlColumnDeclaration(d.name, new BitBooleanExpression(d.value)) : new SqlColumnDeclaration(d.name, d.value)))
                .ToReadOnlyCollection(),
                visitedUpdated.Source,
                visitedUpdated.Where,
                null, null, false, null, null, false, false, new SqlTableExpression("#TEMP")
                                       );

            var selectExpression = new SqlSelectExpression(typeof(void), null, null, selectIntoExpression.Into, null, null);
            var insertExpression = new SqlInsertIntoExpression(visitedUpdated.Source, columnInfos.Select(c => c.GetColumnName()).Concat(insertedColumns.Select(c => c.name)).ToReadOnlyCollection(), null, selectExpression, null, true);
            var deleteExpression = new SqlDeleteExpression(visitedUpdated.Source, visitedUpdated.Where);

            var list = new List <Expression>
            {
                selectIntoExpression,
                deleteExpression,
                new SqlSetCommandExpression("IDENTITY_INSERT", visitedUpdated.Source, new SqlKeywordExpression("ON")),
                insertExpression,
                new SqlSetCommandExpression("IDENTITY_INSERT", visitedUpdated.Source, new SqlKeywordExpression("OFF")),
            };

            return(new SqlStatementListExpression(list));
        }
 protected override void AppendTop(SqlSelectExpression selectExpression)
 {
     if (selectExpression.Take != null && selectExpression.Skip == null)
     {
         Write("TOP(");
         Visit(selectExpression.Take);
         Write(") ");
     }
 }
예제 #11
0
        protected override Expression VisitSelect(SqlSelectExpression selectExpression)
        {
            var count = selectExpression.Columns.Count;
            List <SqlColumnDeclaration> newColumns = null;

            for (var i = 0; i < count; i++)
            {
                var column = selectExpression.Columns[i];
                var visitedColumnExpression = this.Visit(column.Expression);

                if (visitedColumnExpression.Type.GetUnwrappedNullableType() == typeof(bool) && !(visitedColumnExpression is BitBooleanExpression))
                {
                    if (newColumns == null)
                    {
                        newColumns = new List <SqlColumnDeclaration>(selectExpression.Columns.Take(i));
                    }

                    var newColumnExpression  = BitBooleanExpression.Coerce(visitedColumnExpression);
                    var newColumnDeclaration = new SqlColumnDeclaration(column.Name, newColumnExpression);

                    newColumns.Add(newColumnDeclaration);
                }
                else if (visitedColumnExpression != column.Expression)
                {
                    if (newColumns == null)
                    {
                        newColumns = new List <SqlColumnDeclaration>(selectExpression.Columns.Take(i));
                    }

                    newColumns.Add(column.ReplaceExpression(visitedColumnExpression));
                }
                else if (newColumns != null)
                {
                    newColumns.Add(column);
                }
            }

            var from = this.VisitSource(selectExpression.From);

            var where = this.Visit(selectExpression.Where);
            var orderBy = this.VisitExpressionList(selectExpression.OrderBy);
            var groupBy = this.VisitExpressionList(selectExpression.GroupBy);
            var skip    = this.Visit(selectExpression.Skip);
            var take    = this.Visit(selectExpression.Take);

            if (where is BitBooleanExpression)
            {
                where = Expression.Equal(where, Expression.Constant(true, where.Type));
            }

            if (from != selectExpression.From || where != selectExpression.Where || newColumns != selectExpression.Columns || orderBy != selectExpression.OrderBy || groupBy != selectExpression.GroupBy || take != selectExpression.Take || skip != selectExpression.Skip)
            {
                return(new SqlSelectExpression(selectExpression.Type, selectExpression.Alias, newColumns ?? selectExpression.Columns, from, where, orderBy, groupBy, selectExpression.Distinct, skip, take, selectExpression.ForUpdate, selectExpression.Reverse, selectExpression.Into));
            }

            return(base.VisitSelect(selectExpression));
        }
        protected override Expression VisitSelect(SqlSelectExpression selectExpression)
        {
            if (selectExpression.OrderBy != null)
            {
                return(selectExpression.ChangeOrderBy(null));
            }

            return(base.VisitSelect(selectExpression));
        }
        protected override Expression VisitSelect(SqlSelectExpression selectExpression)
        {
            selectNesting++;

            var retval = base.VisitSelect(selectExpression);

            selectNesting--;

            return(retval);
        }
예제 #14
0
 private static bool IsRedudantSubquery(SqlSelectExpression select)
 {
     return((IsSimpleProjection(select) || IsNameMapProjection(select)) &&
            !select.Distinct &&
            select.Take == null &&
            select.Skip == null &&
            select.Where == null &&
            (select.OrderBy == null || select.OrderBy.Count == 0) &&
            (select.GroupBy == null || select.GroupBy.Count == 0));
 }
예제 #15
0
        protected virtual void VisitColumn(SqlSelectExpression selectExpression, SqlColumnDeclaration column)
        {
            var c = this.Visit(column.Expression) as SqlColumnExpression;

            if ((c == null || c.Name != column.Name) && !String.IsNullOrEmpty(column.Name))
            {
                this.Write(" AS ");
                this.WriteQuotedIdentifier(column.Name);
            }
        }
예제 #16
0
        protected override Expression VisitSelect(SqlSelectExpression select)
        {
            var saveIsOuterMostSelect = this.isOuterMostSelect;

            try
            {
                this.isOuterMostSelect = false;

                select = (SqlSelectExpression)base.VisitSelect(select);

                var canHaveOrderBy      = saveIsOuterMostSelect || select.Take != null || select.Skip != null;
                var hasGroupBy          = select.GroupBy?.Count > 0;
                var canReceiveOrderings = canHaveOrderBy && !hasGroupBy && !select.Distinct && !SqlAggregateChecker.HasAggregates(select);

                var hasOrderBy = select.OrderBy?.Count > 0;

                if (hasOrderBy)
                {
                    PrependOrderings(select.OrderBy);
                }

                var columns            = select.Columns;
                var orderings          = canReceiveOrderings ? this.gatheredOrderings : (canHaveOrderBy ? select.OrderBy : null);
                var canPassOnOrderings = !saveIsOuterMostSelect && !hasGroupBy && !select.Distinct && (select.Take == null && select.Skip == null);

                if (this.gatheredOrderings != null)
                {
                    if (canPassOnOrderings)
                    {
                        var producedAliases = SqlAliasesProduced.Gather(select.From);
                        var project         = RebindOrderings(this.gatheredOrderings, select.Alias, producedAliases, select.Columns);

                        this.gatheredOrderings = null;
                        PrependOrderings(project.Orderings);

                        columns = project.Columns;
                    }
                    else
                    {
                        this.gatheredOrderings = null;
                    }
                }

                if (orderings != select.OrderBy || columns != select.Columns)
                {
                    select = new SqlSelectExpression(select.Type, select.Alias, columns, select.From, select.Where, orderings, select.GroupBy, select.Distinct, select.Skip, select.Take, select.ForUpdate);
                }

                return(select);
            }
            finally
            {
                this.isOuterMostSelect = saveIsOuterMostSelect;
            }
        }
예제 #17
0
        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 && SqlAggregateChecker.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 = this.Visit(from.Where);

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

            return(base.VisitSelect(selectExpression));
        }
예제 #18
0
 protected override Expression VisitSelect(SqlSelectExpression select)
 {
     if (this.selectsToRemove.Contains(select))
     {
         return(Visit(select.From));
     }
     else
     {
         return(base.VisitSelect(select));
     }
 }
예제 #19
0
 private static bool IsRedudantSubquery(SqlSelectExpression select)
 {
     return((IsSimpleProjection(select) || IsNameMapProjection(select)) &&
            !select.Distinct &&
            (select.Take == null) &&
            (select.Skip == null) &&
            select.Where == null &&
            !select.Columns.Any(c => c.NoOptimise) &&
            ((select.OrderBy?.Count ?? 0) == 0) &&
            ((select.GroupBy?.Count ?? 0) == 0));
 }
예제 #20
0
        protected override Expression VisitSelect(SqlSelectExpression selectExpression)
        {
            if (selectExpression.GroupBy != null && selectExpression.GroupBy.Count == 1 &&
                selectExpression.GroupBy[0].NodeType == ExpressionType.New)
            {
                var groupBy = ((NewExpression)selectExpression.GroupBy[0]).Arguments;

                return(new SqlSelectExpression(selectExpression.Type, selectExpression.Alias, selectExpression.Columns.ToReadOnlyList(), selectExpression.From, selectExpression.Where, selectExpression.OrderBy.ToReadOnlyList(), groupBy.ToReadOnlyList(), selectExpression.Distinct, selectExpression.Skip, selectExpression.Take, selectExpression.ForUpdate));
            }

            return(base.VisitSelect(selectExpression));
        }
예제 #21
0
        internal static bool IsSimpleProjection(SqlSelectExpression select)
        {
            foreach (var decl in select.Columns)
            {
                if (!(decl.Expression is SqlColumnExpression col) || decl.Name != col.Name)
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #22
0
        protected override Expression VisitSelect(SqlSelectExpression select)
        {
            var columnRemoved = false;

            select = (SqlSelectExpression)base.VisitSelect(select);

            var columnsOrderedByName = select.Columns.OrderBy(c => c.Name).ToList();

            var removedColumns = new BitArray(select.Columns.Count);

            for (int i = 0, n = columnsOrderedByName.Count; i < n - 1; i++)
            {
                var icolumn = columnsOrderedByName[i];
                var iNewColumnExpression = new SqlColumnExpression(icolumn.Expression.Type, select.Alias, icolumn.Name);

                for (var j = i + 1; j < n; j++)
                {
                    if (!removedColumns.Get(j))
                    {
                        var jcolumn = columnsOrderedByName[j];

                        if (IsSameExpression(icolumn.Expression, jcolumn.Expression))
                        {
                            // 'j' references should now be a reference to 'i'

                            var jNewColumnExpression = new SqlColumnExpression(jcolumn.Expression.Type, select.Alias, jcolumn.Name);
                            this.visitedColumns.Add(jNewColumnExpression, iNewColumnExpression);

                            removedColumns.Set(j, true);
                            columnRemoved = true;
                        }
                    }
                }
            }

            if (columnRemoved)
            {
                var newColumnDeclarations = new List <SqlColumnDeclaration>();

                for (int i = 0, n = columnsOrderedByName.Count; i < n; i++)
                {
                    if (!removedColumns.Get(i))
                    {
                        newColumnDeclarations.Add(columnsOrderedByName[i]);
                    }
                }

                select = select.ChangeColumns(newColumnDeclarations);
            }

            return(select);
        }
예제 #23
0
        protected override Expression VisitSelect(SqlSelectExpression select)
        {
            var saveIsOuterMostSelect = this.isOuterMostSelect;

            try
            {
                this.isOuterMostSelect = false;

                select = (SqlSelectExpression)base.VisitSelect(select);

                var hasOrderBy = select.OrderBy != null && select.OrderBy.Count > 0;

                if (hasOrderBy)
                {
                    this.PrependOrderings(select.OrderBy.Select(c => (SqlOrderByExpression)c));
                }

                var canHaveOrderBy     = saveIsOuterMostSelect && !SqlExpressionFinder.FindExists(select, c => c.NodeType == (ExpressionType)SqlExpressionType.Aggregate || c.NodeType == (ExpressionType)SqlExpressionType.AggregateSubquery);
                var canPassOnOrderings = !saveIsOuterMostSelect;

                var columns = select.Columns;
                IEnumerable <Expression> orderings = (canHaveOrderBy) ? this.gatheredOrderings : null;

                if (this.gatheredOrderings != null)
                {
                    if (canPassOnOrderings)
                    {
                        var producedAliases = AliasesProduced.Gather(select.From);
                        var project         = this.RebindOrderings(this.gatheredOrderings, select.Alias, producedAliases, select.Columns);

                        this.gatheredOrderings = project.Orderings;

                        columns = project.Columns;
                    }
                    else
                    {
                        this.gatheredOrderings = null;
                    }
                }

                if (orderings != select.OrderBy || columns != select.Columns)
                {
                    select = new SqlSelectExpression(select.Type, select.Alias, columns, select.From, select.Where, orderings, select.GroupBy, select.Distinct, select.Skip, select.Take, select.ForUpdate);
                }

                return(select);
            }
            finally
            {
                this.isOuterMostSelect = saveIsOuterMostSelect;
            }
        }
            protected override Expression VisitSelect(SqlSelectExpression select)
            {
                var savedIsTopLevel = this.isTopLevel;

                this.isTopLevel = false;

                select = (SqlSelectExpression)base.VisitSelect(select);

                // Attempt to merge subqueries that would have been removed by the above
                // logic except for the existence of a where clause

                while (CanMergeWithFrom(select))
                {
                    var fromSelect = select.From.GetLeftMostSelect();

                    CanMergeWithFrom(select);

                    // remove the redundant subquery
                    select = SqlSubqueryRemover.Remove(select, fromSelect);

                    // merge where expressions
                    var where = select.Where;

                    if (fromSelect.Where != null)
                    {
                        if (where != null)
                        {
                            where = Expression.And(fromSelect.Where, 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;
                    var skip       = select.Skip ?? fromSelect.Skip;
                    var take       = select.Take ?? fromSelect.Take;
                    var isDistinct = select.Distinct || fromSelect.Distinct;

                    if (where != select.Where || orderBy != select.OrderBy || groupBy != select.GroupBy || isDistinct != select.Distinct || skip != select.Skip || take != select.Take)
                    {
                        select = new SqlSelectExpression(select.Type, select.Alias, select.Columns, select.From, where, orderBy, groupBy, isDistinct, skip, take, select.ForUpdate);
                    }
                }

                this.isTopLevel = savedIsTopLevel;

                return(select);
            }
예제 #25
0
        internal static bool IsSimpleProjection(SqlSelectExpression select)
        {
            foreach (SqlColumnDeclaration decl in select.Columns)
            {
                var col = decl.Expression as SqlColumnExpression;

                if (col == null || decl.Name != col.Name)
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #26
0
        protected override Expression VisitSelect(SqlSelectExpression select)
        {
            if (IsRedudantSubquery(select))
            {
                if (this.redundant == null)
                {
                    this.redundant = new List <SqlSelectExpression>();
                }

                this.redundant.Add(select);
            }

            return(select);
        }
예제 #27
0
        protected override Expression VisitSelect(SqlSelectExpression selectExpression)
        {
            this.VisitSource(selectExpression.From);
            this.VisitColumnDeclarations(selectExpression.Columns);

            var localInWhereClause = this.inWhereClause;

            this.inWhereClause = true;

            this.Visit(selectExpression.Where);
            this.inWhereClause = localInWhereClause;

            return(selectExpression);
        }
예제 #28
0
        protected override Expression VisitSelect(SqlSelectExpression selectExpression)
        {
            if (selectExpression.Skip != null)
            {
                var rowNumber = new SqlFunctionCallExpression(typeof(int), "ROW_NUMBER");

                var oldAliases = (selectExpression.From as ISqlExposesAliases)?.Aliases;
                var innerSelectWithRowAlias = selectExpression.Alias + "_ROW";

                var cols = selectExpression.Columns.Select(c => new SqlColumnDeclaration(c.Name, new SqlColumnExpression(c.Expression.Type, selectExpression.Alias, c.Name))).ToList();
                var over = new SqlOverExpression(rowNumber, selectExpression.OrderBy?.Cast <SqlOrderByExpression>().ToReadOnlyCollection() ?? cols.Select(c => new SqlOrderByExpression(OrderType.Ascending, c.Expression)).ToReadOnlyCollection());

                if (oldAliases != null)
                {
                    over = (SqlOverExpression)AliasReferenceReplacer.Replace(over, oldAliases.Contains, selectExpression.Alias);
                }

                var rowColumn = new SqlColumnDeclaration(RowColumnName, over);

                cols.Add(rowColumn);

                var innerSelectWithRowColumns = cols.ToReadOnlyCollection();
                var innerSelectWithRow        = new SqlSelectExpression(selectExpression.Type, innerSelectWithRowAlias, innerSelectWithRowColumns, selectExpression.ChangeOrderBy(null).ChangeSkipTake(null, null), null, null, null, false, null, null, false);
                var outerColumns = selectExpression.Columns.Select(c => new SqlColumnDeclaration(c.Name, new SqlColumnExpression(c.Expression.Type, innerSelectWithRowAlias, c.Name)));

                Expression rowPredicate = Expression.GreaterThan(new SqlColumnExpression(typeof(int), innerSelectWithRowAlias, rowColumn.Name), selectExpression.Skip);

                if (selectExpression.Take != null && !(selectExpression.Take is SqlTakeAllValueExpression))
                {
                    rowPredicate = Expression.And
                                   (
                        rowPredicate,
                        Expression.LessThanOrEqual(new SqlColumnExpression(typeof(int), innerSelectWithRowAlias, rowColumn.Name), Expression.Add(selectExpression.Skip, selectExpression.Take))
                                   );
                }

                var newOrderBy = selectExpression
                                 .OrderBy?
                                 .Select(c => oldAliases == null ? c : AliasReferenceReplacer.Replace(c, oldAliases.Contains, innerSelectWithRowAlias))
                                 .Concat(new SqlOrderByExpression(OrderType.Ascending, new SqlColumnExpression(typeof(int), innerSelectWithRowAlias, rowColumn.Name)))
                                 .ToReadOnlyCollection();

                var retval = new SqlSelectExpression(selectExpression.Type, selectExpression.Alias, outerColumns, innerSelectWithRow, rowPredicate, newOrderBy, selectExpression.ForUpdate);

                return(retval);
            }

            return(base.VisitSelect(selectExpression));
        }
예제 #29
0
        protected override Expression VisitSelect(SqlSelectExpression select)
        {
            select = (SqlSelectExpression)base.VisitSelect(select);

            // Expand all purely redundant subqueries

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

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

            return(select);
        }
예제 #30
0
            private static bool IsColumnProjection(SqlSelectExpression select)
            {
                var count = select.Columns.Count;

                for (var i = 0; i < count; i++)
                {
                    var columnDeclaration = select.Columns[i];

                    if (columnDeclaration.Expression.NodeType != (ExpressionType)SqlExpressionType.Column && columnDeclaration.Expression.NodeType != ExpressionType.Constant)
                    {
                        return(false);
                    }
                }

                return(true);
            }