/// <summary> /// Visits a <see cref="WhereOperator" /> and coalesces it with any possible child operators. /// </summary> /// <param name="op">The operator to visit.</param> /// <returns>The coalesced operator.</returns> protected internal override QueryOperator VisitWhere(WhereOperator op) { var source = VisitAndConvert <MonadMember>(op.Source); var predicate = Visit(op.Predicate); var srcOperator = source.QueryNodeType == QueryNodeType.Operator ? (QueryOperator)source : null; var srcWhere = srcOperator != null && srcOperator.NodeType == OperatorType.Where ? (WhereOperator)srcOperator : null; if (srcWhere != null && op.ElementType == srcWhere.ElementType) { var p = Expression.Parameter(op.ElementType); if (TryExtractNullaryLambdaBody(srcWhere.Predicate, out Expression predicate1) && TryExtractNullaryLambdaBody(predicate, out Expression predicate2)) { var reduced1 = BetaReducer.Reduce(Expression.Invoke(predicate1, p)); var reduced2 = BetaReducer.Reduce(Expression.Invoke(predicate2, p)); return(op.QueryExpressionFactory.Where( op.ElementType, srcWhere.Source, DefaultQueryExpressionFactory.Instance.LambdaAbstraction( Expression.Lambda( Expression.Lambda( Expression.AndAlso(reduced1, reduced2), p ) ), Array.Empty <QueryTree>() ) )); } var predicateType = typeof(Func <,>).MakeGenericType(p.Type, typeof(bool)); var p1 = Expression.Parameter(predicateType); var p2 = Expression.Parameter(predicateType); return(op.QueryExpressionFactory.Where( op.ElementType, srcWhere.Source, DefaultQueryExpressionFactory.Instance.LambdaAbstraction( Expression.Lambda( Expression.Lambda( Expression.AndAlso( Expression.Invoke(p1, p), Expression.Invoke(p2, p) ), p ), p1, p2 ), new[] { srcWhere.Predicate, predicate } ) )); } return(op.Update(source, predicate)); }
/// <summary> /// Visits a <see cref="WhereOperator" /> node. /// </summary> /// <param name="op">Node to visit.</param> /// <returns>Result of visiting the node.</returns> protected internal override QueryOperator VisitWhere(WhereOperator op) { var src = VisitAndConvert <MonadMember>(op.Source); var pred = Visit(op.Predicate); if (src != op.Source || pred != op.Predicate) { return(MakeWhere(op, src, pred)); } return(op); }
/// <summary> /// Makes a <see cref="WhereOperator" /> with the given children. /// </summary> /// <param name="node">Original query expression.</param> /// <param name="source">Source query expression.</param> /// <param name="predicate">Predicate query expression.</param> /// <returns>Representation of the original query expression.</returns> protected sealed override QueryOperator MakeWhere(WhereOperator node, MonadMember source, QueryTree predicate) { return(node.QueryExpressionFactory.Where(node.ElementType, source, predicate)); }
/// <summary> /// Creates a textual representation of the WhereOperator with the given children. /// </summary> /// <param name="node">Original query expression.</param> /// <param name="source">Source query expression.</param> /// <param name="predicate">Predicate query expression.</param> /// <returns>Representation of the original query expression.</returns> protected override string MakeWhere(WhereOperator node, string source, string predicate) { return(string.Format(CultureInfo.InvariantCulture, "@Where({0}, {1})", source, predicate)); }
/// <summary> /// Makes a <see cref="WhereOperator" /> with the given children. /// </summary> /// <param name="node">Original query expression.</param> /// <param name="source">Source query expression.</param> /// <param name="elementType">Element type for the resulting operator.</param> /// <param name="predicate">Predicate query expression.</param> /// <returns>Representation of the original query expression.</returns> protected virtual QueryOperator MakeWhere(WhereOperator node, Type elementType, MonadMember source, QueryTree predicate) { return(node.QueryExpressionFactory.Where(elementType, source, predicate)); }