예제 #1
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);
        }
예제 #2
0
        protected override Expression VisitSelect(SqlSelectExpression selectExpression)
        {
            if (selectExpression.Skip != null)
            {
                const string orderByColumnPrefix = "__$$ORDERBYCOL";

                var rowNumber          = new SqlFunctionCallExpression(typeof(int), "ROW_NUMBER");
                var selectWithRowAlias = selectExpression.Alias + "_ROW";

                var cols = selectExpression
                           .Columns
                           .Select(c => new SqlColumnDeclaration(c.Name, new SqlColumnExpression(c.Expression.Type, selectExpression.Alias, c.Name)))
                           .ToList();

                var aliasedNames = selectExpression.OrderBy == null ? null : new HashSet <string>(selectExpression
                                                                                                  .Columns
                                                                                                  .Select(c => c.Expression)
                                                                                                  .OfType <SqlColumnExpression>()
                                                                                                  .Select(c => c.AliasedName));

                var orderByCols = selectExpression
                                  .OrderBy?
                                  .Where(c => !IsColumnAndAlreadyProjected(c.Expression, aliasedNames))
                                  .Select((c, i) => new SqlColumnDeclaration(orderByColumnPrefix + i, c.Expression)) ?? Enumerable.Empty <SqlColumnDeclaration>();

                SqlOverExpression over;

                if (selectExpression.OrderBy?.Any() == true)
                {
                    var i = 0;

                    over = new SqlOverExpression(rowNumber, selectExpression
                                                 .OrderBy
                                                 .Select(c =>
                    {
                        if (IsColumnAndAlreadyProjected(c.Expression, aliasedNames))
                        {
                            return(new SqlOrderByExpression(c.OrderType, new SqlColumnExpression(c.Type, selectExpression.Alias, ((SqlColumnExpression)c.Expression).Name)));
                        }
                        else
                        {
                            return(new SqlOrderByExpression(c.OrderType, new SqlColumnExpression(c.Type, selectExpression.Alias, orderByColumnPrefix + i++)));
                        }
                    }).ToReadOnlyCollection());
                }
                else
                {
                    over = new SqlOverExpression(rowNumber, cols.Select(c => new SqlOrderByExpression(OrderType.Ascending, c.Expression)).ToReadOnlyCollection());
                }

                var innerSelect = orderByCols == null ? selectExpression : selectExpression.ChangeColumns(selectExpression.Columns.Concat(orderByCols));

                var rowColumn = new SqlColumnDeclaration(RowColumnName, over);

                cols.Add(rowColumn);

                var selectWithRowColumns = cols.ToReadOnlyCollection();
                var selectWithRow        = new SqlSelectExpression(selectExpression.Type, selectWithRowAlias, selectWithRowColumns, Visit(innerSelect.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, selectWithRowAlias, c.Name)));

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

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

                var retval = new SqlSelectExpression(selectExpression.Type, selectExpression.Alias, outerColumns.ToReadOnlyCollection(), selectWithRow, rowPredicate, null, null, selectExpression.Distinct, null, null, selectExpression.ForUpdate, selectExpression.Reverse, selectExpression.Into);

                return(retval);
            }

            return(base.VisitSelect(selectExpression));
        }
예제 #3
0
        protected override Expression VisitSelect(SqlSelectExpression selectExpression)
        {
            List <SqlColumnDeclaration> newColumns = null;

            for (var i = 0; i < selectExpression.Columns.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 where = this.Visit(selectExpression.Where);

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

            if (where != selectExpression.Where)
            {
                if (newColumns != null)
                {
                    return(selectExpression.ChangeWhereAndColumns(where, new ReadOnlyList <SqlColumnDeclaration>(newColumns)));
                }
                else
                {
                    return(selectExpression.ChangeWhere(where));
                }
            }
            else if (newColumns != null)
            {
                return(selectExpression.ChangeColumns(newColumns, true));
            }
            else
            {
                return(base.VisitSelect(selectExpression));
            }
        }