public void VisitorUsesNodeTypeRegistry_ToParseAndAnalyzeSubQueries() { Expression subQuery = ExpressionHelper.MakeExpression(() => CustomSelect(ExpressionHelper.CreateQueryable <Cook>(), s => s)); Expression surroundingExpression = Expression.Lambda(subQuery); // evaluate the ExpressionHelper.CreateQueryable<Cook> () method var inputExpression = PartialEvaluatingExpressionVisitor.EvaluateIndependentSubtrees( surroundingExpression, new TestEvaluatableExpressionFilter()); var emptyNodeTypeRegistry = new MethodInfoBasedNodeTypeRegistry(); emptyNodeTypeRegistry.Register(new[] { ((MethodCallExpression)subQuery).Method }, typeof(SelectExpressionNode)); var newLambdaExpression = (LambdaExpression)SubQueryFindingExpressionVisitor.Process(inputExpression, emptyNodeTypeRegistry); Assert.That(newLambdaExpression.Body, Is.InstanceOf(typeof(SubQueryExpression))); }
public void EvaluateIndependentSubtrees_WithFilter_IsNotEvaluatable_ReturnsOriginalExpression() { var left = Expression.Constant(1); var right = Expression.Constant(2); var expression = Expression.MakeBinary(ExpressionType.Add, left, right); var filterMock = MockRepository.GenerateStrictMock <IEvaluatableExpressionFilter>(); filterMock.Expect(_ => _.IsEvaluatableBinary(expression)).Repeat.Never(); filterMock.Expect(_ => _.IsEvaluatableConstant(left)).Return(false); filterMock.Expect(_ => _.IsEvaluatableConstant(right)).Return(true); filterMock.Replay(); var result = PartialEvaluatingExpressionVisitor.EvaluateIndependentSubtrees(expression, filterMock); Assert.That(result, Is.SameAs(expression)); filterMock.VerifyAllExpectations(); }
public void EvaluateWholeQueryTree_WhoseLambdasAreInMemberExpressions_InsteadOfUnaryExpressions() { var source = ExpressionHelper.CreateQueryable <Cook> (); Expression <Func <Cook, bool> > predicate = s1 => false; var queryExpression = ExpressionHelper.MakeExpression(() => source.Where(predicate)); Assert.That(((MethodCallExpression)queryExpression).Arguments[1].NodeType, Is.EqualTo(ExpressionType.MemberAccess), "Usually, this would be a UnaryExpression (Quote containing the Lambda); but we pass a MemberExpression containing the lambda."); var partiallyEvaluatedExpression = PartialEvaluatingExpressionVisitor.EvaluateIndependentSubtrees( queryExpression, new TestEvaluatableExpressionFilter()); var whereMethodCallExpression = (MethodCallExpression)partiallyEvaluatedExpression; var wherePredicateNavigator = new ExpressionTreeNavigator(whereMethodCallExpression.Arguments[1]); var wherePredicateLambdaNavigator = new ExpressionTreeNavigator((Expression)wherePredicateNavigator.Value); Assert.That(wherePredicateLambdaNavigator.Body.Value, Is.EqualTo(false)); }
public void EvaluateWholeQueryTree_ThatDoesNotUseItsParameters() { var source = ExpressionHelper.CreateQueryable <Cook> (); var query = from s1 in source where false select 0 + int.Parse("0"); var partiallyEvaluatedExpression = PartialEvaluatingExpressionVisitor.EvaluateIndependentSubtrees( query.Expression, new TestEvaluatableExpressionFilter()); var selectMethodCallExpression = (MethodCallExpression)partiallyEvaluatedExpression; var whereMethodCallExpression = (MethodCallExpression)selectMethodCallExpression.Arguments[0]; var selectSelectorNavigator = new ExpressionTreeNavigator(selectMethodCallExpression.Arguments[1]); var wherePredicateNavigator = new ExpressionTreeNavigator(whereMethodCallExpression.Arguments[1]); Assert.That(selectSelectorNavigator.Operand.Body.Value, Is.EqualTo(0)); Assert.That(wherePredicateNavigator.Operand.Body.Value, Is.EqualTo(false)); }
private Expression CreateMemberAccessComparison(ExpressionType expressionType, NewExpression newExpression, Expression otherExpression) { // The ReSharper warning is wrong - newExpression.Members can be null // ReSharper disable ConditionIsAlwaysTrueOrFalse if (newExpression.Members == null || newExpression.Members.Count == 0) // ReSharper restore ConditionIsAlwaysTrueOrFalse { var message = string.Format( "Compound values can only be compared if the respective constructor invocation has members associated with it. Expressions: '{0}', '{1}'", newExpression, otherExpression); throw new NotSupportedException(message); } var combinedComparison = newExpression.Arguments .Select((arg, i) => (Expression)Expression.MakeBinary(expressionType, arg, GetMemberExpression(newExpression.Members[i], otherExpression))) .Aggregate((previous, current) => CombineComparisons(previous, current, expressionType, newExpression, otherExpression)); //TODO RMLNQSQL-91: check if the filter needs to actually filter like it does during building the querymodel return(PartialEvaluatingExpressionVisitor.EvaluateIndependentSubtrees(combinedComparison, new NullEvaluatableExpressionFilter())); }
public void EvaluateIndependentSubtrees_WithFilter_IsEvaluatable_ReturnsEvaluatedExpression() { var left = Expression.Constant(1); var right = Expression.Constant(2); var expression = Expression.MakeBinary(ExpressionType.Add, left, right); var expectedExpression = Expression.Constant(3); var filterMock = MockRepository.GenerateStrictMock <IEvaluatableExpressionFilter>(); filterMock.Expect(_ => _.IsEvaluatableBinary(expression)).Return(true); filterMock.Expect(_ => _.IsEvaluatableConstant(left)).Return(true); filterMock.Expect(_ => _.IsEvaluatableConstant(right)).Return(true); filterMock.Expect(_ => _.IsEvaluatableConstant(Arg <ConstantExpression> .Matches(e => ((int)e.Value) == 3))).Return(true); filterMock.Replay(); var result = PartialEvaluatingExpressionVisitor.EvaluateIndependentSubtrees(expression, filterMock); ExpressionTreeComparer.CheckAreEqualTrees(expectedExpression, result); filterMock.VerifyAllExpectations(); }
public void EvaluateExpression_WithException_BacksOut_AndEvaluatesAsMuchAsPossible() { // "p && <nullVariableHolder.Item1>.Length > (0 + 3)" becomes "p && Exception (NullReferenceException, Exception (NullReferenceException, null.Length) > 3)" var nullVariableHolder = Tuple.Create((string)null, (string)null); var nullExpression = Expression.Property(Expression.Constant(nullVariableHolder), "Item1"); var throwingExpression = Expression.Property(nullExpression, "Length"); var evaluatableOuterExpression = Expression.GreaterThan(throwingExpression, Expression.Add(Expression.Constant(0), Expression.Constant(3))); var nonEvaluatableOutermostExpression = Expression.AndAlso(Expression.Parameter(typeof(bool), "p"), evaluatableOuterExpression); var result = PartialEvaluatingExpressionVisitor.EvaluateIndependentSubtrees( nonEvaluatableOutermostExpression, new TestEvaluatableExpressionFilter()); // p && Exception (...) Assert.That(result, Is.InstanceOf <BinaryExpression> ()); Assert.That(((BinaryExpression)result).Left, Is.SameAs(nonEvaluatableOutermostExpression.Left)); Assert.That(((BinaryExpression)result).Right, Is.TypeOf <PartialEvaluationExceptionExpression> ()); // Exception (NullReferenceException, Exception (...) > 3) var exceptionExpression1 = (PartialEvaluationExceptionExpression)((BinaryExpression)result).Right; Assert.That(exceptionExpression1.Exception, Is.InstanceOf <NullReferenceException>()); var evaluatedExpression1 = exceptionExpression1.EvaluatedExpression; Assert.That(evaluatedExpression1, Is.AssignableTo <BinaryExpression> ()); Assert.That(((BinaryExpression)evaluatedExpression1).Left, Is.TypeOf <PartialEvaluationExceptionExpression>()); Assert.That(((BinaryExpression)evaluatedExpression1).Right, Is.InstanceOf <ConstantExpression> ().With.Property("Value").EqualTo(3)); // Exception (NullReferenceException, null.Length) var exceptionExpression2 = (PartialEvaluationExceptionExpression)((BinaryExpression)evaluatedExpression1).Left; Assert.That(exceptionExpression2.Exception, Is.InstanceOf <NullReferenceException> ()); Assert.That(exceptionExpression2.EvaluatedExpression, Is.InstanceOf <MemberExpression> ()); var memberExpression = ((MemberExpression)exceptionExpression2.EvaluatedExpression); Assert.That(memberExpression.Expression, Is.InstanceOf <ConstantExpression>().With.Property("Value").EqualTo(null)); Assert.That(memberExpression.Member, Is.EqualTo(typeof(string).GetProperty("Length"))); }
protected void CheckQuery( QueryModel queryModel, string expectedStatement, Expression <Func <IDatabaseResultRow, object> > expectedInMemoryProjection, bool simplifyInMemoryProjection, params CommandParameter[] expectedParameters) { var result = GenerateSql(queryModel); try { Assert.That(result.CommandText, Is.EqualTo(expectedStatement)); } catch { Console.WriteLine("Full generated statement: " + result.CommandText); Console.WriteLine("Full expected statement: " + expectedStatement); throw; } Assert.That(result.Parameters, Is.EqualTo(expectedParameters)); if (expectedInMemoryProjection != null) { Expression checkedInMemoryProjection = expectedInMemoryProjection; if (simplifyInMemoryProjection) { // TODO RMLNQSQL-91: This point requires the actual method filter checkedInMemoryProjection = PartialEvaluatingExpressionVisitor.EvaluateIndependentSubtrees( checkedInMemoryProjection, new TestEvaluatableExpressionFilter()); checkedInMemoryProjection = ReplaceConvertExpressionMarker(checkedInMemoryProjection); } SqlExpressionTreeComparer.CheckAreEqualTrees(checkedInMemoryProjection, result.GetInMemoryProjection <object> ()); } }
public Expression Process(Expression expressionTree) { ArgumentUtility.CheckNotNull("expressionTree", expressionTree); return(PartialEvaluatingExpressionVisitor.EvaluateIndependentSubtrees(expressionTree, _filter)); }
public static Expression EvaluateIndependentSubtrees(Expression expression) { var evaluatedExpression = PartialEvaluatingExpressionVisitor.EvaluateIndependentSubtrees(expression, new NhEvaluatableExpressionFilter()); return(new NhPartialEvaluatingExpressionVisitor().Visit(evaluatedExpression)); }
object IQueryProvider.Execute(Expression expression) { try { var hashingVisitor = new HashingExpressionVisitor(); expression = hashingVisitor.Visit(expression); var constantParameterizingVisitor = new ConstantParameterizingExpressionVisitor(); expression = constantParameterizingVisitor.Visit(expression); var parameterMapping = constantParameterizingVisitor.Mapping; if (!QueryCache.TryGetValue(hashingVisitor.HashCode, out var compiled)) { expression = new QueryableExpandingExpressionVisitor(parameterMapping).Visit(expression); expression = new PartialEvaluatingExpressionVisitor().Visit(expression); var preCompositionVisitors = new[] { ExpressionVisitorProvider.OptimizingExpressionVisitors, ExpressionVisitorProvider.MidOptimizationExpressionVisitors, ExpressionVisitorProvider.OptimizingExpressionVisitors, }; expression = preCompositionVisitors.SelectMany(vs => vs).Aggregate(expression, (e, v) => v.Visit(e)); expression = new QueryActivatingExpressionVisitor(this).Visit(expression); expression = new QueryComposingExpressionVisitor(ExpressionVisitorProvider).Visit(expression); var postCompositionVisitors = new[] { ExpressionVisitorProvider.OptimizingExpressionVisitors, }; expression = postCompositionVisitors.SelectMany(vs => vs).Aggregate(expression, (e, v) => v.Visit(e)); var queryProviderParameter = Expression.Parameter(typeof(ImpatientQueryProvider), "queryProvider"); expression = new QueryCompilingExpressionVisitor(ExpressionVisitorProvider, queryProviderParameter).Visit(expression); var parameters = new ParameterExpression[parameterMapping.Count + 1]; parameters[0] = queryProviderParameter; parameterMapping.Values.CopyTo(parameters, 1); compiled = Expression.Lambda(expression, parameters).Compile(); QueryCache.Add(hashingVisitor.HashCode, compiled); } var arguments = new object[parameterMapping.Count + 1]; arguments[0] = this; parameterMapping.Keys.CopyTo(arguments, 1); return(compiled.DynamicInvoke(arguments)); } catch (TargetInvocationException targetInvocationException) { throw targetInvocationException.InnerException; } }
public void Hashing() { var hasher = new HashingExpressionVisitor(); // No closure Expression <Func <string> > expr1 = () => "hello".ToString().Substring(0, 1); Expression <Func <string> > expr2 = () => "hello".ToString().Substring(0, 1); hasher.Visit(expr1); var hashCode1 = hasher.HashCode; hasher.Reset(); hasher.Visit(expr2); var hashCode2 = hasher.HashCode; hasher.Reset(); Assert.AreNotEqual(expr1, expr2); Assert.AreEqual(hashCode1, hashCode2); // Closure Expression <Func <string> > CreateExpressionWithClosure(int value) { Expression <Func <string> > expression = () => "hello".ToString().Substring(value, 1); return(expression); } var expr3 = CreateExpressionWithClosure(0); var expr4 = CreateExpressionWithClosure(1); hasher.Visit(expr3); var hashCode3 = hasher.HashCode; hasher.Reset(); hasher.Visit(expr4); var hashCode4 = hasher.HashCode; hasher.Reset(); Assert.AreNotEqual(expr3, expr4); Assert.AreEqual(hashCode3, hashCode4); // Partially evaluated var evaluator = new PartialEvaluatingExpressionVisitor(); Expression <Func <string> > expr5 = () => "hello".ToString().Substring(0, 1); var expr6 = CreateExpressionWithClosure(0); hasher.Visit(evaluator.Visit(expr5)); var hashCode5 = hasher.HashCode; hasher.Reset(); hasher.Visit(evaluator.Visit(expr6)); var hashCode6 = hasher.HashCode; hasher.Reset(); Assert.AreNotEqual(expr5, expr6); Assert.AreEqual(hashCode5, hashCode6); }