private bool CanBeJoinCondition(Expression expression, HashSet <TableAlias> left, HashSet <TableAlias> right, HashSet <TableAlias> all) { var referenced = DbReferencedAliasGatherer.Gather(expression); var leftOkay = referenced.Intersect(left).Any(); var rightOkay = referenced.Intersect(right).Any(); var subset = referenced.IsSubsetOf(all); return(leftOkay && rightOkay && subset); }
public static HashSet <TableAlias> Gather(Expression source) { var gatherer = new DbReferencedAliasGatherer(); if (gatherer != null) { gatherer.Visit(source); } return(gatherer.aliases); }
private bool GetEquiJoinKeyExpressions(Expression predicate, TableAlias outerAlias, List <Expression> outerExpressions, List <Expression> innerExpressions) { if (predicate.NodeType == ExpressionType.Equal) { var b = predicate as BinaryExpression; var leftCol = this.GetColumnExpression(b.Left); var rightCol = this.GetColumnExpression(b.Right); if (leftCol != null && rightCol != null) { if (leftCol.Alias == outerAlias) { outerExpressions.Add(b.Left); innerExpressions.Add(b.Right); return(true); } else if (rightCol.Alias == outerAlias) { innerExpressions.Add(b.Left); outerExpressions.Add(b.Right); return(true); } } } var hadKey = false; var parts = predicate.Split(ExpressionType.And, ExpressionType.AndAlso); if (parts.Length > 1) { foreach (var part in parts) { var hasOuterAliasReference = DbReferencedAliasGatherer.Gather(part).Contains(outerAlias); if (hasOuterAliasReference) { if (GetEquiJoinKeyExpressions(part, outerAlias, outerExpressions, innerExpressions) == false) { return(false); } hadKey = true; } } } return(hadKey); }
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); }