コード例 #1
0
        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));
        }
コード例 #2
0
        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));
        }
コード例 #3
0
        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));
        }