public override Expression Resolve(ParameterExpression inputParameter, Expression expressionToBeResolved, ClauseGenerationContext clauseGenerationContext) { var convertExpression = Expression.Convert(inputParameter, SearchedItemType); var expressionWithCast = ReplacingExpressionTreeVisitor.Replace(inputParameter, convertExpression, expressionToBeResolved); return(Source.Resolve(inputParameter, expressionWithCast, clauseGenerationContext)); }
public void Process(AggregateResultOperator resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree) { var inputExpr = ((StreamedSequenceInfo)queryModelVisitor.PreviousEvaluationType).ItemExpression; var inputType = inputExpr.Type; var paramExpr = Expression.Parameter(inputType, "item"); var accumulatorFunc = Expression.Lambda( ReplacingExpressionTreeVisitor.Replace(inputExpr, paramExpr, resultOperator.Func.Body), resultOperator.Func.Parameters[0], paramExpr); // NH-3850: changed from list transformer (working on IEnumerable<object>) to post execute // transformer (working on IEnumerable<inputType>) for globally aggregating polymorphic results // instead of aggregating results for each class separately and yielding only the first. // If the aggregation relies on ordering, final result will still be wrong due to // polymorphic results being union-ed without re-ordering. (This is a limitation of all polymorphic // queries, this is not specific to LINQ provider.) var inputList = Expression.Parameter(typeof(IEnumerable <>).MakeGenericType(inputType), "inputList"); var aggregate = ReflectionCache.EnumerableMethods.AggregateDefinition.MakeGenericMethod(inputType); MethodCallExpression call = Expression.Call( aggregate, inputList, accumulatorFunc ); tree.AddPostExecuteTransformer(Expression.Lambda(call, inputList)); // There is no more a list transformer yielding an IList<resultType>, but this aggregate case // have inputType = resultType, so no further action is required. }
public void Process(AggregateResultOperator resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree) { var inputExpr = ((StreamedSequenceInfo)queryModelVisitor.PreviousEvaluationType).ItemExpression; var inputType = inputExpr.Type; var paramExpr = Expression.Parameter(inputType, "item"); var accumulatorFunc = Expression.Lambda( ReplacingExpressionTreeVisitor.Replace(inputExpr, paramExpr, resultOperator.Func.Body), resultOperator.Func.Parameters[0], paramExpr); var inputList = Expression.Parameter(typeof(IEnumerable <>).MakeGenericType(typeof(object)), "inputList"); var castToItem = ReflectionCache.EnumerableMethods.CastDefinition.MakeGenericMethod(new[] { inputType }); var castToItemExpr = Expression.Call(castToItem, inputList); var aggregate = ReflectionCache.EnumerableMethods.AggregateDefinition.MakeGenericMethod(inputType); MethodCallExpression call = Expression.Call( aggregate, castToItemExpr, accumulatorFunc ); tree.AddListTransformer(Expression.Lambda(call, inputList)); }
public void VisitUnknownNonExtensionExpression_Ignored() { var expression = new UnknownExpression(typeof(object)); var result = ReplacingExpressionTreeVisitor.Replace(_replacedNode, _replacementNode, expression); Assert.That(result, Is.SameAs(expression)); }
public override Expression Resolve(ParameterExpression inputParameter, Expression expressionToBeResolved, ClauseGenerationContext clauseGenerationContext) { // we modify the structure of the stream of data coming into this node by our result selector, // so we first resolve the result selector, then we substitute the result for the inputParameter in the expressionToBeResolved var resolvedResultSelector = GetResolvedResultSelector(clauseGenerationContext); return(ReplacingExpressionTreeVisitor.Replace(inputParameter, resolvedResultSelector, expressionToBeResolved)); }
public void IgnoresTree_WhenReplacedNodeDoesNotExist() { var tree = ExpressionHelper.CreateLambdaExpression(); var result = ReplacingExpressionTreeVisitor.Replace(_replacedNode, _replacementNode, tree); Assert.That(result, Is.SameAs(tree)); }
public void ReplacesGivenNode_ByGivenReplacement() { var tree = _replacedNode; var result = ReplacingExpressionTreeVisitor.Replace(_replacedNode, _replacementNode, tree); Assert.That(result, Is.SameAs(_replacementNode)); }
public override Expression Resolve( ParameterExpression inputParameter, Expression expressionToBeResolved, ClauseGenerationContext clauseGenerationContext) { Utils.CheckNotNull("inputParameter", inputParameter); Utils.CheckNotNull("expressionToBeResolved", expressionToBeResolved); var resolvedSelector = GetResolvedAdaptedSelector(clauseGenerationContext); return(ReplacingExpressionTreeVisitor.Replace(inputParameter, resolvedSelector, expressionToBeResolved)); }
public void VisitExtensionExpression_DescendsIntoChildren() { var tree = new VBStringComparisonExpression(_replacedNode, true); var result = ReplacingExpressionTreeVisitor.Replace(_replacedNode, _replacementNode, tree); var expected = new VBStringComparisonExpression(_replacementNode, true); ExpressionTreeComparer.CheckAreEqualTrees(expected, result); }
public void ReplacesTreePart() { var tree = Expression.MakeBinary(ExpressionType.Add, Expression.Constant(0), _replacedNode); var result = ReplacingExpressionTreeVisitor.Replace(_replacedNode, _replacementNode, tree); var expectedResult = Expression.MakeBinary(ExpressionType.Add, Expression.Constant(0), _replacementNode); ExpressionTreeComparer.CheckAreEqualTrees(expectedResult, result); }
private static IQueryable <T> CreateQuery <T, TR>( IQueryable <T> source, Expression <Func <IQueryable <T>, TR> > expression) { var newQueryExpression = ReplacingExpressionTreeVisitor.Replace( expression.Parameters[0], source.Expression, expression.Body); return(source.Provider.CreateQuery <T>(newQueryExpression)); }
public override Expression Resolve( ParameterExpression inputParameter, Expression expressionToBeResolved, ClauseGenerationContext clauseGenerationContext) { ArgumentUtility.CheckNotNull("inputParameter", inputParameter); ArgumentUtility.CheckNotNull("expressionToBeResolved", expressionToBeResolved); var convertExpression = Expression.Convert(inputParameter, CastItemType); var expressionWithCast = ReplacingExpressionTreeVisitor.Replace(inputParameter, convertExpression, expressionToBeResolved); return(Source.Resolve(inputParameter, expressionWithCast, clauseGenerationContext)); }
/// <summary> /// Replaces the given parameter with a back-reference to the <see cref="IQuerySource"/> corresponding to <paramref name="referencedNode"/>. /// </summary> /// <param name="referencedNode">The referenced node.</param> /// <param name="parameterToReplace">The parameter to replace with a <see cref="QuerySourceReferenceExpression"/>.</param> /// <param name="expression">The expression in which to replace the parameter.</param> /// <param name="context">The clause generation context.</param> /// <returns><paramref name="expression"/>, with <paramref name="parameterToReplace"/> replaced with a <see cref="QuerySourceReferenceExpression"/> /// pointing to the clause corresponding to <paramref name="referencedNode"/>.</returns> public static Expression ReplaceParameterWithReference( IQuerySourceExpressionNode referencedNode, ParameterExpression parameterToReplace, Expression expression, ClauseGenerationContext context) { var clause = GetQuerySourceForNode(referencedNode, context); var referenceExpression = new QuerySourceReferenceExpression(clause); return(ReplacingExpressionTreeVisitor.Replace(parameterToReplace, referenceExpression, expression)); }
public static Expression Resolve <TParameter, TResult> ( IQuerySource sourceToReference, Expression <Func <TParameter, TResult> > expressionToBeResolved) { ArgumentUtility.CheckNotNull("sourceToReference", sourceToReference); ArgumentUtility.CheckNotNull("expressionToBeResolved", expressionToBeResolved); return(ReplacingExpressionTreeVisitor.Replace( expressionToBeResolved.Parameters[0], new QuerySourceReferenceExpression(sourceToReference), expressionToBeResolved.Body)); }
public void ReplacesTreePart_InSubQueries() { var replacedNode = ExpressionHelper.CreateQueryable <Cook> ().Expression; var replacementNode = Expression.Constant(null, typeof(Cook[])); var subQueryMainFromClause = new MainFromClause("c", typeof(Cook), replacedNode); var subQuery = ExpressionHelper.CreateQueryModel(subQueryMainFromClause); var tree = new SubQueryExpression(subQuery); ReplacingExpressionTreeVisitor.Replace(replacedNode, replacementNode, tree); Assert.That(subQueryMainFromClause.FromExpression, Is.SameAs(replacementNode)); }
/// <summary> /// Replaces the given parameter with a back-reference to the <see cref="IQuerySource"/> corresponding to <paramref name="referencedNode"/>. /// </summary> /// <param name="referencedNode">The referenced node.</param> /// <param name="parameterToReplace">The parameter to replace with a <see cref="QuerySourceReferenceExpression"/>.</param> /// <param name="expression">The expression in which to replace the parameter.</param> /// <param name="context">The clause generation context.</param> /// <returns><paramref name="expression"/>, with <paramref name="parameterToReplace"/> replaced with a <see cref="QuerySourceReferenceExpression"/> /// pointing to the clause corresponding to <paramref name="referencedNode"/>.</returns> public static Expression ReplaceParameterWithReference( IQuerySourceExpressionNode referencedNode, ParameterExpression parameterToReplace, Expression expression, ClauseGenerationContext context) { ArgumentUtility.CheckNotNull("referencedNode", referencedNode); ArgumentUtility.CheckNotNull("parameterToReplace", parameterToReplace); ArgumentUtility.CheckNotNull("expression", expression); ArgumentUtility.CheckNotNull("context", context); var clause = GetQuerySourceForNode(referencedNode, context); var referenceExpression = new QuerySourceReferenceExpression(clause); return(ReplacingExpressionTreeVisitor.Replace(parameterToReplace, referenceExpression, expression)); }
public void SetUp() { _querySource = ExpressionHelper.CreateMainFromClause_Int(); _sourceExpression = new QuerySourceReferenceExpression(_querySource); var originalFunc = ExpressionHelper.CreateLambdaExpression <int, int, int> ((total, i) => total + i); _func = Expression.Lambda( ReplacingExpressionTreeVisitor.Replace(originalFunc.Parameters[1], _sourceExpression, originalFunc.Body), originalFunc.Parameters[0]); _resultSelector = ExpressionHelper.CreateLambdaExpression <int, string> (total => total.ToString()); _seed = Expression.Constant(12); _resultOperatorWithoutResultSelector = new AggregateFromSeedResultOperator(_seed, _func, null); _resultOperatorWithResultSelector = new AggregateFromSeedResultOperator(_seed, _func, _resultSelector); }
/// <summary> /// Wraps the query in a deferred <see cref="IFutureValue{T}"/> which will trigger a batch of all pending future queries /// when its <see cref="IFutureValue{T}.Value"/> is read. /// </summary> /// <param name="source">An <see cref="T:System.Linq.IQueryable`1" /> to convert to a future query.</param> /// <param name="selector">An aggregation function to apply to <paramref name="source"/>.</param> /// <typeparam name="TSource">The type of the elements of <paramref name="source" />.</typeparam> /// <typeparam name="TResult">The type of the value returned by the function represented by <paramref name="selector"/>.</typeparam> /// <returns>A <see cref="IFutureValue{T}"/>.</returns> /// <exception cref="T:System.ArgumentNullException"><paramref name="source" /> is <see langword="null"/>.</exception> /// <exception cref="T:System.NotSupportedException"><paramref name="source" /> <see cref="IQueryable.Provider"/> is not a <see cref="INhQueryProvider"/>.</exception> public static IFutureValue <TResult> ToFutureValue <TSource, TResult>(this IQueryable <TSource> source, Expression <Func <IQueryable <TSource>, TResult> > selector) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (!(source.Provider is INhQueryProvider provider)) { throw new NotSupportedException($"Source {nameof(source.Provider)} must be a {nameof(INhQueryProvider)}"); } var expression = ReplacingExpressionTreeVisitor .Replace(selector.Parameters.Single(), source.Expression, selector.Body); return(provider.ExecuteFutureValue <TResult>(expression)); }
public void Process(AggregateFromSeedResultOperator resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree) { var inputExpr = ((StreamedSequenceInfo)queryModelVisitor.PreviousEvaluationType).ItemExpression; var inputType = inputExpr.Type; var paramExpr = Expression.Parameter(inputType, "item"); var accumulatorFunc = Expression.Lambda( ReplacingExpressionTreeVisitor.Replace(inputExpr, paramExpr, resultOperator.Func.Body), resultOperator.Func.Parameters[0], paramExpr); var accumulatorType = resultOperator.Func.Parameters[0].Type; var inputList = Expression.Parameter(typeof(IEnumerable <>).MakeGenericType(typeof(object)), "inputList"); var castToItem = ReflectionCache.EnumerableMethods.CastDefinition.MakeGenericMethod(new[] { inputType }); var castToItemExpr = Expression.Call(castToItem, inputList); MethodCallExpression call; if (resultOperator.OptionalResultSelector == null) { var aggregate = ReflectionCache.EnumerableMethods.AggregateWithSeedDefinition .MakeGenericMethod(inputType, accumulatorType); call = Expression.Call( aggregate, castToItemExpr, resultOperator.Seed, accumulatorFunc ); } else { var selectorType = resultOperator.OptionalResultSelector.Type.GetGenericArguments()[2]; var aggregate = ReflectionCache.EnumerableMethods.AggregateWithSeedAndResultSelectorDefinition .MakeGenericMethod(inputType, accumulatorType, selectorType); call = Expression.Call( aggregate, castToItemExpr, resultOperator.Seed, accumulatorFunc, resultOperator.OptionalResultSelector ); } tree.AddListTransformer(Expression.Lambda(call, inputList)); }
public static IFutureValue <TResult> ToFutureValue <T, TResult>(this IQueryable <T> query, Expression <Func <IQueryable <T>, TResult> > selector) { var nhQueryable = query as QueryableBase <T>; if (nhQueryable == null) { throw new NotSupportedException("Query needs to be of type QueryableBase<T>"); } var provider = (INhQueryProvider)query.Provider; var expression = ReplacingExpressionTreeVisitor.Replace(selector.Parameters.Single(), query.Expression, selector.Body); return((IFutureValue <TResult>)provider.ExecuteFuture(expression)); }
public override Expression Resolve( ParameterExpression inputParameter, Expression expressionToBeResolved, ClauseGenerationContext clauseGenerationContext) { Utils.CheckNotNull("inputParameter", inputParameter); Utils.CheckNotNull("expressionToBeResolved", expressionToBeResolved); if (IsLetNode) { // We modify the structure of the stream of data coming into this node by our selector, // so we first resolve the selector (adapted to include a reference to the let clause), then we substitute the result for the inputParameter // in the expressionToBeResolved. var resolvedSelector = GetResolvedAdaptedSelector(clauseGenerationContext); return(ReplacingExpressionTreeVisitor.Replace(inputParameter, resolvedSelector, expressionToBeResolved)); } return(base.Resolve(inputParameter, expressionToBeResolved, clauseGenerationContext)); }
private Expression CreateAggregate(Expression fromClauseExpression, LambdaExpression body, Func <Expression, Expression> aggregateFactory, Func <ResultOperatorBase> resultOperatorFactory) { var fromClause = new MainFromClause(_nameGenerator.GetNewName(), body.Parameters[0].Type, fromClauseExpression); var selectClause = body.Body; selectClause = ReplacingExpressionTreeVisitor.Replace(body.Parameters[0], new QuerySourceReferenceExpression( fromClause), selectClause); var queryModel = new QueryModel(fromClause, new SelectClause(aggregateFactory(selectClause))); // TODO - this sucks, but we use it to get the Type of the SubQueryExpression correct queryModel.ResultOperators.Add(resultOperatorFactory()); var subQuery = new SubQueryExpression(queryModel); queryModel.ResultOperators.Clear(); return(subQuery); }
public static Expression ResolveLambdaParameter <TParameter1, TParameter2, TResult> ( int parameterToResolveIndex, IQuerySource source, Expression <Func <TParameter1, TParameter2, TResult> > expressionToBeResolved) { ArgumentUtility.CheckNotNull("source", source); ArgumentUtility.CheckNotNull("expressionToBeResolved", expressionToBeResolved); var parameterToResolve = expressionToBeResolved.Parameters[parameterToResolveIndex]; var resolvedBody = ReplacingExpressionTreeVisitor.Replace( parameterToResolve, new QuerySourceReferenceExpression(source), expressionToBeResolved.Body); var remainingParameters = new List <ParameterExpression> (expressionToBeResolved.Parameters); remainingParameters.Remove(parameterToResolve); return(Expression.Lambda(resolvedBody, remainingParameters.ToArray())); }
// Takes a queryable and a transformation of that queryable and returns an expression representing that transformation, // This is required to get an expression with a result operator such as Count or First. // Use as follows: // var query = from ... select ...; // var countExpression = MakeExpression (query, q => q.Count()); private Expression MakeExpression <TSource, TResult> (IQueryable <TSource> queryable, Expression <Func <IQueryable <TSource>, TResult> > func) { return(ReplacingExpressionTreeVisitor.Replace(func.Parameters[0], queryable.Expression, func.Body)); }
private LambdaExpression CreateFunc <TA1, TA2, TR> (Expression <Func <TA1, TA2, TR> > originalFunc) { return(Expression.Lambda( ReplacingExpressionTreeVisitor.Replace(originalFunc.Parameters[1], _sourceExpression, originalFunc.Body), originalFunc.Parameters[0])); }