protected override Expression VisitSelect(SelectExpression select) { bool saveIsOuterMostSelect = this.isOuterMostSelect; try { this.isOuterMostSelect = false; var saveSuppressOrderBy = this.suppressOrderby; this.suppressOrderby = false; var saveGatheredOrderings = this.gatheredOrderings; if (saveSuppressOrderBy) { this.gatheredOrderings = null; this.isOuterMostSelect = true; } select = (SelectExpression)base.VisitSelect(select); this.suppressOrderby = saveSuppressOrderBy; if (saveSuppressOrderBy) { this.gatheredOrderings = saveGatheredOrderings; } bool hasOrderBy = select.OrderBy != null && select.OrderBy.Count > 0; bool hasGroupBy = select.GroupBy != null && select.GroupBy.Count > 0; bool canHaveOrderBy = saveIsOuterMostSelect || select.Take != null || select.Skip != null; bool canReceiveOrderings = canHaveOrderBy && !hasGroupBy && !select.IsDistinct && !AggregateChecker.HasAggregates(select) && !suppressOrderby; if (hasOrderBy) { this.PrependOrderings(select.OrderBy); } if (select.IsReverse) { if (this.gatheredOrderings == null || gatheredOrderings.Count == 0) { throw new NotSupportedException(string.Format(Res.OperationNotSupported, "", "Reverse", "if no 'OrderBy' expression.")); } for (int i = 0, n = this.gatheredOrderings.Count; i < n; i++) { var ord = this.gatheredOrderings[i]; this.gatheredOrderings[i] = new OrderExpression( ord.OrderType == OrderType.Ascending ? OrderType.Descending : OrderType.Ascending, ord.Expression ); } } IEnumerable <OrderExpression> orderings = null; if (canReceiveOrderings) { orderings = this.gatheredOrderings; } else if (canHaveOrderBy) { orderings = select.OrderBy; } bool canPassOnOrderings = !saveIsOuterMostSelect && !hasGroupBy && !select.IsDistinct && !suppressOrderby; ReadOnlyCollection <ColumnDeclaration> columns = select.Columns; if (this.gatheredOrderings != null) { if (canPassOnOrderings) { var producedAliases = TableAliasGatherer.Gather(select.From); // 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 = null; this.PrependOrderings(project.Orderings); columns = project.Columns; } else { this.gatheredOrderings = null; } } if (orderings != select.OrderBy || columns != select.Columns || select.IsReverse) { select = new SelectExpression(select.Alias, columns, select.From, select.Where, orderings, select.GroupBy, select.IsDistinct, select.Skip, select.Take, false); } return(select); } finally { this.isOuterMostSelect = saveIsOuterMostSelect; } }
public static HashSet<TableAlias> Gather(Expression source) { var gatherer = new TableAliasGatherer(); gatherer.Visit(source); return gatherer.aliases; }