protected override Expression VisitSelect(SelectExpression select)
 {
     select = (SelectExpression)base.VisitSelect(select);
     if (lookup.Contains(select.Alias))
     {
         List<FieldDeclaration> aggFields = new List<FieldDeclaration>(select.Fields);
         foreach (AggregateSubqueryExpression ae in lookup[select.Alias])
         {
             string name = "agg" + aggFields.Count;
             var colType = this.language.TypeSystem.GetStorageType(ae.Type);
             FieldDeclaration cd = new FieldDeclaration(name, ae.AggregateInGroupSelect, colType);
             this.map.Add(ae, new FieldExpression(ae.Type, colType, ae.GroupByAlias, name));
             aggFields.Add(cd);
         }
         return new SelectExpression(select.Alias, aggFields, select.From, select.Where, select.OrderBy, select.GroupBy, select.IsDistinct, select.Skip, select.Take, select.IsReverse);
     }
     return select;
 }
 protected virtual bool CompareFieldDeclaration(FieldDeclaration a, FieldDeclaration b)
 {
     return a.Name == b.Name && this.Compare(a.Expression, b.Expression);
 }
        protected override Expression VisitSelect(SelectExpression select)
        {
            // visit field projection first
            ReadOnlyCollection<FieldDeclaration> fields = select.Fields;

            var wasRetained = this.retainAllFields;
            this.retainAllFields = false;

            List<FieldDeclaration> alternate = null;
            for (int i = 0, n = select.Fields.Count; i < n; i++)
            {
                FieldDeclaration decl = select.Fields[i];
                if (wasRetained || select.IsDistinct || IsFieldUsed(select.Alias, decl.Name))
                {
                    Expression expr = this.Visit(decl.Expression);
                    if (expr != decl.Expression)
                    {
                        decl = new FieldDeclaration(decl.Name, expr, decl.QueryType);
                    }
                }
                else
                {
                    decl = null;  // null means it gets omitted
                }
                if (decl != select.Fields[i] && alternate == null)
                {
                    alternate = new List<FieldDeclaration>();
                    for (int j = 0; j < i; j++)
                    {
                        alternate.Add(select.Fields[j]);
                    }
                }
                if (decl != null && alternate != null)
                {
                    alternate.Add(decl);
                }
            }
            if (alternate != null)
            {
                fields = 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);

            ClearFieldsUsed(select.Alias);

            if (fields != select.Fields
                || take != select.Take
                || skip != select.Skip
                || orderbys != select.OrderBy
                || groupbys != select.GroupBy
                || where != select.Where
                || from != select.From)
            {
                select = new SelectExpression(select.Alias, fields, from, where, orderbys, groupbys, select.IsDistinct, skip, take, select.IsReverse);
            }

            this.retainAllFields = wasRetained;

            return select;
        }
 public static SelectExpression RemoveField(this SelectExpression select, FieldDeclaration field)
 {
     List<FieldDeclaration> fields = new List<FieldDeclaration>(select.Fields);
     fields.Remove(field);
     return select.SetFields(fields);
 }