internal static HashSet <string> Gather(Expression source, TextWriter logger)
        {
            AliasesProduced produced = new AliasesProduced(logger);

            produced.Visit(source);
            return(produced.aliases);
        }
        protected override Expression VisitSelect(SelectExpression select)
        {
            bool saveIsOuterMostSelect = this.isOuterMostSelect;

            try {
                this.isOuterMostSelect = false;
                select = (SelectExpression)base.VisitSelect(select);
                bool hasOrderBy = select.OrderBy != null && select.OrderBy.Count > 0;
                if (hasOrderBy)
                {
                    this.PrependOrderings(select.OrderBy);
                }
                bool canHaveOrderBy     = saveIsOuterMostSelect;
                bool canPassOnOrderings = !saveIsOuterMostSelect && (select.GroupBy == null || select.GroupBy.Count == 0);
                IEnumerable <OrderExpression>          orderings = (canHaveOrderBy) ? this.gatheredOrderings : null;
                ReadOnlyCollection <ColumnDeclaration> columns   = select.Columns;
                if (this.gatheredOrderings != null)
                {
                    if (canPassOnOrderings)
                    {
                        HashSet <string> producedAliases = AliasesProduced.Gather(select.From, Logger);
                        // reproject order expressions using this select's alias so the outer select will have properly formed expressions
                        BindResult 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 SelectExpression(select.Type, select.Alias, columns, select.From, select.Where, orderings, select.GroupBy);
                }
                return(select);
            }
            finally {
                this.isOuterMostSelect = saveIsOuterMostSelect;
            }
        }