protected override Expression VisitSelect(SelectExpression select) { // visit column projection first ReadOnlyCollection <ColumnDeclaration> columns = select.Columns; var wasRetained = this.retainAllColumns; this.retainAllColumns = false; List <ColumnDeclaration> alternate = null; for (int i = 0, n = select.Columns.Count; i < n; i++) { ColumnDeclaration decl = select.Columns[i]; if (wasRetained || select.IsDistinct || IsColumnUsed(select.Alias, decl.Name)) { Expression expr = this.Visit(decl.Expression); if (expr != decl.Expression) { decl = new ColumnDeclaration(decl.Name, expr, decl.SqlType); } } else { decl = null; // null means it gets omitted } if (decl != select.Columns[i] && alternate == null) { alternate = new List <ColumnDeclaration>(); for (int j = 0; j < i; j++) { alternate.Add(select.Columns[j]); } } if (decl != null && alternate != null) { alternate.Add(decl); } } if (alternate != null) { columns = alternate.AsReadOnly(); } Expression take = this.Visit(select.Take); Expression skip = this.Visit(select.Skip); ReadOnlyCollection <Expression> groupbys = this.VisitExpressionList(select.GroupBy); ReadOnlyCollection <OrderExpression> orderbys = this.VisitOrderBy(select.OrderBy); Expression where = this.Visit(select.Where); Expression from = this.Visit(select.From); ClearColumnsUsed(select.Alias); if (columns != select.Columns || take != select.Take || skip != select.Skip || orderbys != select.OrderBy || groupbys != select.GroupBy || where != select.Where || from != select.From) { select = new SelectExpression(select.Alias, columns, from, where, orderbys, groupbys, select.IsDistinct, skip, take, select.IsReverse); } this.retainAllColumns = wasRetained; return(select); }