Beispiel #1
0
        private HqlTreeNode TranslateEqualityComparison(BinaryExpression expression)
        {
            var lhs = VisitExpression(expression.Left).ToArithmeticExpression();
            var rhs = VisitExpression(expression.Right).ToArithmeticExpression();

            // Check for nulls on left or right.
            if (VisitorUtil.IsNullConstant(expression.Right))
            {
                rhs = null;
            }

            if (VisitorUtil.IsNullConstant(expression.Left))
            {
                lhs = null;
            }

            if (lhs == null && rhs == null)
            {
                return(_hqlTreeBuilder.True());
            }

            if (lhs == null)
            {
                return(_hqlTreeBuilder.IsNull(rhs));
            }

            if (rhs == null)
            {
                return(_hqlTreeBuilder.IsNull((lhs)));
            }

            var lhsNullable = IsNullable(lhs);
            var rhsNullable = IsNullable(rhs);

            var equality = _hqlTreeBuilder.Equality(lhs, rhs);

            if (!lhsNullable || !rhsNullable)
            {
                return(equality);
            }

            var lhs2 = VisitExpression(expression.Left).ToArithmeticExpression();
            var rhs2 = VisitExpression(expression.Right).ToArithmeticExpression();

            return(_hqlTreeBuilder.BooleanOr(
                       equality,
                       _hqlTreeBuilder.BooleanAnd(
                           _hqlTreeBuilder.IsNull(lhs2),
                           _hqlTreeBuilder.IsNull(rhs2))));
        }
        private static bool IsConstructionToNullComparison(Expression expression)
        {
            var testExpression = expression as BinaryExpression;

            if (testExpression != null)
            {
                if ((IsConstruction(testExpression.Left) && VisitorUtil.IsNullConstant(testExpression.Right)) ||
                    (IsConstruction(testExpression.Right) && VisitorUtil.IsNullConstant(testExpression.Left)))
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #3
0
        private void FindNotNullMember(BinaryExpression binaryExpression, List <MemberExpression> notNullMembers)
        {
            _equalityNotNullMembers[binaryExpression] = notNullMembers;
            if (binaryExpression.NodeType != ExpressionType.NotEqual)
            {
                return;
            }

            MemberExpression memberExpression;

            if (VisitorUtil.IsNullConstant(binaryExpression.Right) && TryGetMemberAccess(binaryExpression.Left, out memberExpression))
            {
                notNullMembers.Add(memberExpression);
            }
            else if (VisitorUtil.IsNullConstant(binaryExpression.Left) && TryGetMemberAccess(binaryExpression.Right, out memberExpression))
            {
                notNullMembers.Add(memberExpression);
            }
        }
        private HqlTreeNode TranslateEqualityComparison(BinaryExpression expression, HqlExpression lhs, HqlExpression rhs, Func <HqlExpression, HqlTreeNode> applyNullComparison, Func <HqlExpression, HqlExpression, HqlTreeNode> applyRegularComparison)
        {
            // Check for nulls on left or right.
            if (VisitorUtil.IsNullConstant(expression.Right))
            {
                rhs = null;
            }
            if (VisitorUtil.IsNullConstant(expression.Left))
            {
                lhs = null;
            }

            // Need to check for boolean equality
            if (lhs is HqlBooleanExpression || rhs is HqlBooleanExpression)
            {
                if (lhs != null)
                {
                    lhs = GetExpressionForBooleanEquality(expression.Left, lhs);
                }
                if (rhs != null)
                {
                    rhs = GetExpressionForBooleanEquality(expression.Right, rhs);
                }
            }

            if (lhs == null)
            {
                return(applyNullComparison(rhs));
            }
            if (rhs == null)
            {
                return(applyNullComparison(lhs));
            }

            return(applyRegularComparison(lhs, rhs));
        }
Beispiel #5
0
        protected override Expression VisitBinaryExpression(BinaryExpression expression)
        {
            var result = base.VisitBinaryExpression(expression);

            if (expression.NodeType == ExpressionType.AndAlso)
            {
                HandleBinaryOperation((a, b) => a.AndAlso(b));
            }
            else if (expression.NodeType == ExpressionType.OrElse)
            {
                HandleBinaryOperation((a, b) => a.OrElse(b));
            }
            else if (expression.NodeType == ExpressionType.NotEqual && VisitorUtil.IsNullConstant(expression.Right))
            {
                // Discard result from right null.  Left is visited first, so it's below right on the stack.
                _values.Pop();

                HandleUnaryOperation(pvs => pvs.IsNotNull());
            }
            else if (expression.NodeType == ExpressionType.NotEqual && VisitorUtil.IsNullConstant(expression.Left))
            {
                // Discard result from left null.
                var right = _values.Pop();
                _values.Pop();                 // Discard left.
                _values.Push(right);

                HandleUnaryOperation(pvs => pvs.IsNotNull());
            }
            else if (expression.NodeType == ExpressionType.Equal && VisitorUtil.IsNullConstant(expression.Right))
            {
                // Discard result from right null.  Left is visited first, so it's below right on the stack.
                _values.Pop();

                HandleUnaryOperation(pvs => pvs.IsNull());
            }
            else if (expression.NodeType == ExpressionType.Equal && VisitorUtil.IsNullConstant(expression.Left))
            {
                // Discard result from left null.
                var right = _values.Pop();
                _values.Pop();                 // Discard left.
                _values.Push(right);

                HandleUnaryOperation(pvs => pvs.IsNull());
            }
            else if (expression.NodeType == ExpressionType.Coalesce)
            {
                HandleBinaryOperation((a, b) => a.Coalesce(b));
            }
            else if (expression.NodeType == ExpressionType.Add || expression.NodeType == ExpressionType.AddChecked)
            {
                HandleBinaryOperation((a, b) => a.Add(b, expression.Type));
            }
            else if (expression.NodeType == ExpressionType.Divide)
            {
                HandleBinaryOperation((a, b) => a.Divide(b, expression.Type));
            }
            else if (expression.NodeType == ExpressionType.Modulo)
            {
                HandleBinaryOperation((a, b) => a.Modulo(b, expression.Type));
            }
            else if (expression.NodeType == ExpressionType.Multiply || expression.NodeType == ExpressionType.MultiplyChecked)
            {
                HandleBinaryOperation((a, b) => a.Multiply(b, expression.Type));
            }
            else if (expression.NodeType == ExpressionType.Power)
            {
                HandleBinaryOperation((a, b) => a.Power(b, expression.Type));
            }
            else if (expression.NodeType == ExpressionType.Subtract || expression.NodeType == ExpressionType.SubtractChecked)
            {
                HandleBinaryOperation((a, b) => a.Subtract(b, expression.Type));
            }
            else if (expression.NodeType == ExpressionType.And)
            {
                HandleBinaryOperation((a, b) => a.And(b, expression.Type));
            }
            else if (expression.NodeType == ExpressionType.Or)
            {
                HandleBinaryOperation((a, b) => a.Or(b, expression.Type));
            }
            else if (expression.NodeType == ExpressionType.ExclusiveOr)
            {
                HandleBinaryOperation((a, b) => a.ExclusiveOr(b, expression.Type));
            }
            else if (expression.NodeType == ExpressionType.LeftShift)
            {
                HandleBinaryOperation((a, b) => a.LeftShift(b, expression.Type));
            }
            else if (expression.NodeType == ExpressionType.RightShift)
            {
                HandleBinaryOperation((a, b) => a.RightShift(b, expression.Type));
            }
            else if (expression.NodeType == ExpressionType.Equal)
            {
                HandleBinaryOperation((a, b) => a.Equal(b));
            }
            else if (expression.NodeType == ExpressionType.NotEqual)
            {
                HandleBinaryOperation((a, b) => a.NotEqual(b));
            }
            else if (expression.NodeType == ExpressionType.GreaterThanOrEqual)
            {
                HandleBinaryOperation((a, b) => a.GreaterThanOrEqual(b));
            }
            else if (expression.NodeType == ExpressionType.GreaterThan)
            {
                HandleBinaryOperation((a, b) => a.GreaterThan(b));
            }
            else if (expression.NodeType == ExpressionType.LessThan)
            {
                HandleBinaryOperation((a, b) => a.LessThan(b));
            }
            else if (expression.NodeType == ExpressionType.LessThanOrEqual)
            {
                HandleBinaryOperation((a, b) => a.LessThanOrEqual(b));
            }

            return(result);
        }
Beispiel #6
0
        private HqlTreeNode TranslateInequalityComparison(BinaryExpression expression)
        {
            var lhs = VisitExpression(expression.Left).ToArithmeticExpression();
            var rhs = VisitExpression(expression.Right).ToArithmeticExpression();

            // Check for nulls on left or right.
            if (VisitorUtil.IsNullConstant(expression.Right))
            {
                rhs = null;
            }
            if (VisitorUtil.IsNullConstant(expression.Left))
            {
                lhs = null;
            }

            if (lhs == null && rhs == null)
            {
                return(_hqlTreeBuilder.False());
            }

            if (lhs == null)
            {
                return(_hqlTreeBuilder.IsNotNull(rhs));
            }

            if (rhs == null)
            {
                return(_hqlTreeBuilder.IsNotNull(lhs));
            }

            var lhsNullable = IsNullable(lhs);
            var rhsNullable = IsNullable(rhs);

            var inequality = _hqlTreeBuilder.Inequality(lhs, rhs);

            if (!lhsNullable && !rhsNullable)
            {
                return(inequality);
            }

            var lhs2 = VisitExpression(expression.Left).ToArithmeticExpression();
            var rhs2 = VisitExpression(expression.Right).ToArithmeticExpression();

            HqlBooleanExpression booleanExpression;

            if (lhsNullable && rhsNullable)
            {
                booleanExpression = _hqlTreeBuilder.Inequality(
                    _hqlTreeBuilder.IsNull(lhs2).ToArithmeticExpression(),
                    _hqlTreeBuilder.IsNull(rhs2).ToArithmeticExpression());
            }
            else if (lhsNullable)
            {
                booleanExpression = _hqlTreeBuilder.IsNull(lhs2);
            }
            else
            {
                booleanExpression = _hqlTreeBuilder.IsNull(rhs2);
            }

            return(_hqlTreeBuilder.BooleanOr(inequality, booleanExpression));
        }
Beispiel #7
0
        public bool IsNullable(Expression expression, BinaryExpression equalityExpression)
        {
            switch (expression.NodeType)
            {
            case ExpressionType.Convert:
            case ExpressionType.ConvertChecked:
            case ExpressionType.TypeAs:
                // a cast will not return null if the operand is not null (as long as TypeAs is not translated to
                // try_convert in SQL).
                return(IsNullable(((UnaryExpression)expression).Operand, equalityExpression));

            case ExpressionType.Not:
            case ExpressionType.And:
            case ExpressionType.Or:
            case ExpressionType.ExclusiveOr:
            case ExpressionType.LeftShift:
            case ExpressionType.RightShift:
            case ExpressionType.AndAlso:
            case ExpressionType.OrElse:
            case ExpressionType.Equal:
            case ExpressionType.NotEqual:
            case ExpressionType.GreaterThanOrEqual:
            case ExpressionType.GreaterThan:
            case ExpressionType.LessThan:
            case ExpressionType.LessThanOrEqual:
                return(false);

            case ExpressionType.Add:
            case ExpressionType.AddChecked:
            case ExpressionType.Divide:
            case ExpressionType.Modulo:
            case ExpressionType.Multiply:
            case ExpressionType.MultiplyChecked:
            case ExpressionType.Power:
            case ExpressionType.Subtract:
            case ExpressionType.SubtractChecked:
                var binaryExpression = (BinaryExpression)expression;
                return(IsNullable(binaryExpression.Left, equalityExpression) || IsNullable(binaryExpression.Right, equalityExpression));

            case ExpressionType.ArrayIndex:
                return(true);                        // for indexed lists we cannot determine whether the item will be null or not

            case ExpressionType.Coalesce:
                return(IsNullable(((BinaryExpression)expression).Right, equalityExpression));

            case ExpressionType.Conditional:
                var conditionalExpression = (ConditionalExpression)expression;
                return(IsNullable(conditionalExpression.IfTrue, equalityExpression) ||
                       IsNullable(conditionalExpression.IfFalse, equalityExpression));

            case ExpressionType.Call:
                var methodInfo = ((MethodCallExpression)expression).Method;
                return(!_functionRegistry.TryGetGenerator(methodInfo, out var method) || method.AllowsNullableReturnType(methodInfo));

            case ExpressionType.MemberAccess:
                return(IsNullable((MemberExpression)expression, equalityExpression));

            case ExpressionType.Extension:
                return(IsNullableExtension(expression, equalityExpression));

            case ExpressionType.TypeIs:                     // an equal or in operator will be generated and those cannot return null
            case ExpressionType.NewArrayInit:
                return(false);

            case ExpressionType.Constant:
                return(VisitorUtil.IsNullConstant(expression));

            case ExpressionType.Parameter:
                return(!expression.Type.IsValueType);

            default:
                return(true);
            }
        }