protected override Expression VisitJoin(DbJoinExpression join) { join = base.VisitJoin(join) as DbJoinExpression; if (join.JoinType == JoinType.CrossJoin && this.currentWhere != null) { var declaredLeft = DbDeclaredAliasGatherer.Gather(join.Left); var declaredRight = DbDeclaredAliasGatherer.Gather(join.Right); var declared = new HashSet <TableAlias>(declaredLeft.Union(declaredRight)); var exprs = this.currentWhere.Split(ExpressionType.And, ExpressionType.AndAlso); var good = exprs.Where(e => CanBeJoinCondition(e, declaredLeft, declaredRight, declared)).ToList(); if (good.Count > 0) { var condition = good.Join(ExpressionType.And); join = this.UpdateJoin(join, JoinType.InnerJoin, join.Left, join.Right, condition); var newWhere = exprs.Where(e => !good.Contains(e)).Join(ExpressionType.And); this.currentWhere = newWhere; } } return(join); }
private void MapAliases(Expression a, Expression b) { var prodA = DbDeclaredAliasGatherer.Gather(a).ToArray(); var prodB = DbDeclaredAliasGatherer.Gather(b).ToArray(); for (int i = 0, n = prodA.Length; i < n; i++) { this.aliasScope.Add(prodA[i], prodB[i]); } }
public static HashSet <TableAlias> Gather(Expression source) { var gatherer = new DbDeclaredAliasGatherer(); if (gatherer != null) { gatherer.Visit(source); } return(gatherer.aliases); }
protected override Expression VisitJoin(DbJoinExpression join) { join = base.VisitJoin(join) as DbJoinExpression; if (join.JoinType == JoinType.CrossApply || join.JoinType == JoinType.OuterApply) { if (join.Right is DbTableExpression) { return(new DbJoinExpression(JoinType.CrossJoin, join.Left, join.Right, null)); } if (join.Right is DbSelectExpression select && select.Take == null && select.Skip == null && !DbAggregateChecker.HasAggregates(select) && (select.GroupBy == null || select.GroupBy.Count == 0)) { var selectWithoutWhere = select.SetWhere(null); var referencedAliases = DbReferencedAliasGatherer.Gather(selectWithoutWhere); var declaredAliases = DbDeclaredAliasGatherer.Gather(join.Left); if (referencedAliases != null) { referencedAliases.IntersectWith(declaredAliases); } if (referencedAliases.Count == 0) { var where = select.Where; select = selectWithoutWhere; var pc = DbColumnProjector.ProjectColumns(this.language, where, select.Columns, select.Alias, DbDeclaredAliasGatherer.Gather(select.From)); select = select.SetColumns(pc.Columns); where = pc.Projector; var jt = (where == null) ? JoinType.CrossJoin : (join.JoinType == JoinType.CrossApply ? JoinType.InnerJoin : JoinType.LeftOuter); return(new DbJoinExpression(jt, join.Left, select, where)); } } } return(join); }
internal virtual Expression GetOuterJoinTest(DbSelectExpression select) { var aliases = DbDeclaredAliasGatherer.Gather(select.From); var joinColumns = JoinColumnGatherer.Gather(aliases, select).ToList(); if (joinColumns.Count > 0) { foreach (var jc in joinColumns) { foreach (var col in select.Columns) { if (jc.Equals(col.Expression)) { return(jc); } } } return(joinColumns[0]); } return(Expression.Constant(1, typeof(int?))); }
private Expression MakeSubquery(Expression expression) { var newAlias = new TableAlias(); var aliases = DbDeclaredAliasGatherer.Gather(expression); var decls = new List <DbColumnDeclaration>(); foreach (var ta in aliases) { foreach (var col in this.columns[ta]) { var name = decls.GetAvailableColumnName(col.Name); var decl = new DbColumnDeclaration(name, col, col.QueryType); decls.Add(decl); var newCol = new DbColumnExpression(col.Type, col.QueryType, newAlias, col.Name); this.map.Add(col, newCol); } } return(new DbSelectExpression(newAlias, decls, expression, null)); }
protected override Expression VisitSelect(DbSelectExpression select) { bool saveIsOuterMostSelect = this.isOuterMostSelect; try { this.isOuterMostSelect = false; select = base.VisitSelect(select) as DbSelectExpression; var hasOrderBy = select.OrderBy != null && select.OrderBy.Count > 0; var hasGroupBy = select.GroupBy != null && select.GroupBy.Count > 0; var canHaveOrderBy = saveIsOuterMostSelect || select.Take != null || select.Skip != null; var canReceiveOrderings = canHaveOrderBy && !hasGroupBy && !select.IsDistinct && !DbAggregateChecker.HasAggregates(select); if (hasOrderBy) { this.PrependOrderings(select.OrderBy); } if (select.IsReverse) { this.ReverseOrderings(); } var orderings = null as IEnumerable <DbOrderExpression>; if (canReceiveOrderings) { orderings = this.gatheredOrderings; } else if (canHaveOrderBy) { orderings = select.OrderBy; } var canPassOnOrderings = !saveIsOuterMostSelect && !hasGroupBy && !select.IsDistinct; var columns = select.Columns; if (this.gatheredOrderings != null) { if (canPassOnOrderings) { var producedAliases = DbDeclaredAliasGatherer.Gather(select.From); var 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 DbSelectExpression(select.Alias, columns, select.From, select.Where, orderings, select.GroupBy, select.IsDistinct, select.Skip, select.Take, false); } return(select); } finally { this.isOuterMostSelect = saveIsOuterMostSelect; } }