protected virtual JoinQuery CreateJoinQuery(IExecutionContext context, [NotNull] IMultiPartQuery query) { var filter = query.GetFilter(context); var leftFilter = filter.RemoveAllPartsThatAreNotInSource(this.Left); var rightFilter = filter.RemoveAllPartsThatAreNotInSource(this.Right); var resultFilter = filter.SplitByAndExpressions() .Except(leftFilter.SplitByAndExpressions(), JoinSourceBase.ExpressionComparer) .Except(rightFilter.SplitByAndExpressions(), JoinSourceBase.ExpressionComparer) .DefaultIfEmpty() .Aggregate(Expression.AndAlso); var leftQuery = new MultiPartQuery { Fields = query.GetUsedFields(this.Left, resultFilter), FilterExpression = leftFilter, }; var rightQuery = new MultiPartQuery { Fields = query.GetUsedFields(this.Right, resultFilter), FilterExpression = leftFilter, }; return(new JoinQuery(leftQuery, rightQuery, resultFilter, query.OrderByExpressions)); }
protected override JoinQuery CreateJoinQuery(IExecutionContext context, [NotNull] IMultiPartQuery query) { var resultFilter = query.GetFilter(context); var leftQuery = new MultiPartQuery { Fields = query.GetUsedFields(this.Left, resultFilter), }; var rightQuery = new MultiPartQuery { Fields = query.GetUsedFields(this.Right, resultFilter), }; return(new JoinQuery(leftQuery, rightQuery, resultFilter, query.OrderByExpressions)); }
protected virtual JoinQuery CreateJoinQuery(IExecutionContext context, [NotNull] IMultiPartQuery query, Expression joinFilter) { var filterParts = (query.FilterExpression == null ? joinFilter : Expression.AndAlso(query.GetFilter(context), joinFilter)).SplitByAndExpressions(); // Get all parts of the query that contain fields from both sources. var joinParts = filterParts.OfType <CompareExpression>() .Where(comparison => { var fields = comparison.GetFields().Select(f => f.SourceAlias).ToArray(); return(fields.Intersect(this.Left.Aliases).Any() && fields.Intersect(this.Right.Aliases).Any()); }) .ToArray(); // What's left are the filters for only one source. These we can split in a left part, a right part, and a filter part over the result. var filter = filterParts.Except(joinParts, new ExpressionComparer()).DefaultIfEmpty().Aggregate(Expression.AndAlso); var leftFilter = filter.RemoveAllPartsThatAreNotInSource(this.Left); var rightFilter = filter.RemoveAllPartsThatAreNotInSource(this.Right); var resultFilter = filter.Except(leftFilter, rightFilter); var joinExpression = joinParts.OrderBy(p => p, new MostSpecificComparer()).First().MoveFieldsToTheLeft(this.Left); var ascending = joinExpression.CompareType != ExpressionType.GreaterThan && joinExpression.CompareType != ExpressionType.GreaterThanOrEqual; var leftQuery = new MultiPartQuery { Fields = query.Fields .Where(f => this.Left.Aliases.Contains(f.SourceAlias)) .Concat(joinParts.SelectMany(l => l.GetDataSourceFields(this.Left))) .Concat(resultFilter.GetDataSourceFields(this.Left)) .Distinct(), FilterExpression = leftFilter, OrderByExpressions = new[] { new OrderByExpression(joinExpression.Left, ascending) }, }; var rightQuery = new MultiPartQuery { Fields = query.Fields .Where(f => this.Right.Aliases.Contains(f.SourceAlias)) .Concat(joinParts.SelectMany(l => l.GetDataSourceFields(this.Right))) .Concat(resultFilter.GetDataSourceFields(this.Right)) .Distinct(), FilterExpression = rightFilter, OrderByExpressions = new[] { new OrderByExpression(joinExpression.Right, ascending) }, }; var exraJoinFilter = GenericVisitor.Visit( (ExecutionContextExpression e) => Expression.Constant(context), joinParts.Skip(1).DefaultIfEmpty().Aggregate <Expression>(Expression.AndAlso)); return(new JoinQuery( leftQuery, rightQuery, joinExpression.Left.GetRowExpression <Row>(), joinExpression.CompareType, joinExpression.Right.GetRowExpression <Row>(), joinParts.DefaultIfEmpty <Expression>().Aggregate(Expression.AndAlso), exraJoinFilter.GetJoinFunction(this.Left), query.OrderByExpressions, resultFilter)); }