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); }
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)); }
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)); } }