示例#1
0
        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")));
        }
示例#8
0
        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));
        }
示例#10
0
        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;
            }
        }
示例#12
0
        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);
        }