private HqlExpression GetExpressionForBooleanEquality(Expression @operator, HqlExpression original)
        {
            //When the expression is a constant then use the constant
            var operandEx = @operator as ConstantExpression;

            if (operandEx != null)
            {
                NamedParameter namedParameter;
                if (_parameters.ConstantToParameterMap.TryGetValue(operandEx, out namedParameter))
                {
                    _parameters.RequiredHqlParameters.Add(new NamedParameterDescriptor(namedParameter.Name, null, false));
                    return(_hqlTreeBuilder.Parameter(namedParameter.Name).AsExpression());
                }

                return(_hqlTreeBuilder.Constant(operandEx.Value));
            }

            //When the expression is a member-access not nullable then use the HbmDot
            var memberAccessExpression = @operator as MemberExpression;

            if (ExpressionType.MemberAccess.Equals(@operator.NodeType) && memberAccessExpression != null && typeof(bool) == memberAccessExpression.Type)
            {
                // this case make the difference when the property "Value" of a nullable type is used (ignore the null since the user is explicity checking the Value)
                return(original);
            }

            var subQueryExpression = @operator as SubQueryExpression;

            if (subQueryExpression != null)
            {
                var resultOperators = subQueryExpression.QueryModel.ResultOperators;
                if (resultOperators.Count == 1 &&
                    (resultOperators[0] is FirstResultOperator ||
                     resultOperators[0] is SingleResultOperator))
                {
                    return(original);
                }
            }

            //When the expression is a member-access nullable then use the "case" clause to transform it to boolean (to use always .NET meaning instead leave the DB the behavior for null)
            //When the expression is a complex-expression then use the "case" clause to transform it to boolean
            return(_hqlTreeBuilder.Case(new[] { _hqlTreeBuilder.When(original, _hqlTreeBuilder.True()) }, _hqlTreeBuilder.False()));
        }
Beispiel #2
0
        internal static HqlExpression ToArithmeticExpression(this HqlTreeNode node)
        {
            var hqlBooleanExpression = node as HqlBooleanExpression;

            if (hqlBooleanExpression != null)
            {
                var builder = new HqlTreeBuilder();

                return(builder.Case(new[] { builder.When(hqlBooleanExpression, builder.True()) }, builder.False()));
            }

            return((HqlExpression)node);
        }
        private static HqlExpression ConvertBooleanToCase(HqlExpression node)
        {
            if (node is HqlBooleanExpression)
            {
                var builder = new HqlTreeBuilder();

                return(builder.Case(
                           new HqlWhen[] { builder.When(node, builder.True()) },
                           builder.False()));
            }

            return(node);
        }
Beispiel #4
0
        protected HqlTreeNode VisitConditionalExpression(ConditionalExpression expression)
        {
            var test    = VisitExpression(expression.Test).ToBooleanExpression();
            var ifTrue  = VisitExpression(expression.IfTrue).ToArithmeticExpression();
            var ifFalse = (expression.IfFalse != null
                                                           ? VisitExpression(expression.IfFalse).ToArithmeticExpression()
                                                           : null);

            HqlExpression @case = _hqlTreeBuilder.Case(new[] { _hqlTreeBuilder.When(test, ifTrue) }, ifFalse);

            return((expression.Type == typeof(bool) || expression.Type == (typeof(bool?)))
                                           ? @case
                                           : _hqlTreeBuilder.Cast(@case, expression.Type));
        }
Beispiel #5
0
        protected HqlTreeNode VisitConditionalExpression(ConditionalExpression expression)
        {
            var test    = VisitExpression(expression.Test).ToBooleanExpression();
            var ifTrue  = VisitExpression(expression.IfTrue).ToArithmeticExpression();
            var ifFalse = (expression.IfFalse != null
                                                           ? VisitExpression(expression.IfFalse).ToArithmeticExpression()
                                                           : null);

            HqlExpression @case = _hqlTreeBuilder.Case(new[] { _hqlTreeBuilder.When(test, ifTrue) }, ifFalse);

            // If both operands are parameters, HQL will not be able to determine the resulting type before
            // parameters binding. But it has to compute result set columns type before parameters are bound,
            // so an artificial cast is introduced to hint HQL at the resulting type.
            return(expression.Type == typeof(bool) || expression.Type == typeof(bool?)
                                ? @case
                                : _hqlTreeBuilder.TransparentCast(@case, expression.Type));
        }
Beispiel #6
0
        public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection <Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            // Instance a.CompareTo(b) or static string.Compare(a, b)?
            Expression lhs = arguments.Count == 1 ? targetObject : arguments[0];
            Expression rhs = arguments.Count == 1 ? arguments[0] : arguments[1];

            HqlExpression lhs1 = visitor.Visit(lhs).AsExpression();
            HqlExpression rhs1 = visitor.Visit(rhs).AsExpression();
            HqlExpression lhs2 = visitor.Visit(lhs).AsExpression();
            HqlExpression rhs2 = visitor.Visit(rhs).AsExpression();

            // CASE WHEN (table.[Name] = N'Foo') THEN 0
            //      WHEN (table.[Name] > N'Foo') THEN 1
            //      ELSE -1 END

            return(treeBuilder.Case(
                       new[]
            {
                treeBuilder.When(treeBuilder.Equality(lhs1, rhs1), treeBuilder.Constant(0)),
                treeBuilder.When(treeBuilder.GreaterThan(lhs2, rhs2), treeBuilder.Constant(1))
            },
                       treeBuilder.Constant(-1)));
        }
Beispiel #7
0
        public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection <Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            var when = treeBuilder.When(visitor.Visit(arguments[0]).AsExpression(), visitor.Visit(arguments[1]).AsExpression());

            return(treeBuilder.Case(new[] { when }, visitor.Visit(arguments[2]).AsExpression()));
        }
Beispiel #8
0
        protected HqlTreeNode VisitBinaryExpression(BinaryExpression expression)
        {
            var lhs = VisitExpression(expression.Left).AsExpression();
            var rhs = VisitExpression(expression.Right).AsExpression();

            switch (expression.NodeType)
            {
            case ExpressionType.Equal:
                // Need to check for boolean equality
                if (lhs is HqlBooleanExpression || rhs is HqlBooleanExpression)
                {
                    lhs =
                        _hqlTreeBuilder.Case(
                            new [] { _hqlTreeBuilder.When(lhs, _hqlTreeBuilder.Constant(1)) },
                            _hqlTreeBuilder.Constant(0));

                    rhs =
                        _hqlTreeBuilder.Case(
                            new [] { _hqlTreeBuilder.When(rhs, _hqlTreeBuilder.Constant(1)) },
                            _hqlTreeBuilder.Constant(0));

                    return(_hqlTreeBuilder.Equality(lhs, rhs));
                }

                // Also check for nullability
                if (expression.Left.Type.IsNullableOrReference() || expression.Right.Type.IsNullableOrReference())
                {
                    // TODO - yuck.  This clone is needed because the AST tree nodes are not immutable,
                    // and sharing nodes between multiple branches will cause issues in the hqlSqlWalker phase -
                    // a node, x, gets visited during the walk and updated to refer to a real property.  Later in
                    // the walk, x get revisited (since we copied it here), but now the type doesn't match what
                    // the parser expects.  So we can't share.  Implementing Clone() on HqlTreeNode would be better
                    // that doing a full visit of the Expression tree.  Allowing shared nodes in the AST would be better
                    // still, but might be more work
                    var lhs2 = VisitExpression(expression.Left).AsExpression();
                    var rhs2 = VisitExpression(expression.Right).AsExpression();

                    return(_hqlTreeBuilder.BooleanOr(
                               _hqlTreeBuilder.BooleanAnd(
                                   _hqlTreeBuilder.IsNull(lhs),
                                   _hqlTreeBuilder.IsNull(rhs)),
                               _hqlTreeBuilder.Equality(lhs2, rhs2)
                               ));
                }

                return(_hqlTreeBuilder.Equality(lhs, rhs));

            case ExpressionType.NotEqual:
                // Need to check for boolean in-equality
                if (lhs is HqlBooleanExpression || rhs is HqlBooleanExpression)
                {
                    lhs =
                        _hqlTreeBuilder.Case(
                            new [] { _hqlTreeBuilder.When(lhs, _hqlTreeBuilder.Constant(1)) },
                            _hqlTreeBuilder.Constant(0));

                    rhs =
                        _hqlTreeBuilder.Case(
                            new [] { _hqlTreeBuilder.When(rhs, _hqlTreeBuilder.Constant(1)) },
                            _hqlTreeBuilder.Constant(0));

                    return(_hqlTreeBuilder.Inequality(lhs, rhs));
                }

                // Also check for nullability
                if (expression.Left.Type.IsNullableOrReference() || expression.Right.Type.IsNullableOrReference())
                {
                    var lhs2 = VisitExpression(expression.Left).AsExpression();
                    var rhs2 = VisitExpression(expression.Right).AsExpression();
                    var lhs3 = VisitExpression(expression.Left).AsExpression();
                    var rhs3 = VisitExpression(expression.Right).AsExpression();

                    return
                        (_hqlTreeBuilder.BooleanOr(
                             _hqlTreeBuilder.BooleanOr(
                                 _hqlTreeBuilder.BooleanAnd(
                                     _hqlTreeBuilder.IsNull(lhs),
                                     _hqlTreeBuilder.IsNotNull(rhs)),
                                 _hqlTreeBuilder.BooleanAnd(
                                     _hqlTreeBuilder.IsNotNull(lhs2),
                                     _hqlTreeBuilder.IsNull(rhs2))
                                 ),
                             _hqlTreeBuilder.Inequality(lhs3, rhs3)));
                }

                return(_hqlTreeBuilder.Inequality(lhs, rhs));

            case ExpressionType.And:
                return(_hqlTreeBuilder.BitwiseAnd(lhs, rhs));

            case ExpressionType.AndAlso:
                return(_hqlTreeBuilder.BooleanAnd(lhs.AsBooleanExpression(), rhs.AsBooleanExpression()));

            case ExpressionType.Or:
                return(_hqlTreeBuilder.BitwiseOr(lhs, rhs));

            case ExpressionType.OrElse:
                return(_hqlTreeBuilder.BooleanOr(lhs.AsBooleanExpression(), rhs.AsBooleanExpression()));

            case ExpressionType.Add:
                return(_hqlTreeBuilder.Add(lhs, rhs));

            case ExpressionType.Subtract:
                return(_hqlTreeBuilder.Subtract(lhs, rhs));

            case ExpressionType.Multiply:
                return(_hqlTreeBuilder.Multiply(lhs, rhs));

            case ExpressionType.Divide:
                return(_hqlTreeBuilder.Divide(lhs, rhs));

            case ExpressionType.LessThan:
                return(_hqlTreeBuilder.LessThan(lhs, rhs));

            case ExpressionType.LessThanOrEqual:
                return(_hqlTreeBuilder.LessThanOrEqual(lhs, rhs));

            case ExpressionType.GreaterThan:
                return(_hqlTreeBuilder.GreaterThan(lhs, rhs));

            case ExpressionType.GreaterThanOrEqual:
                return(_hqlTreeBuilder.GreaterThanOrEqual(lhs, rhs));
            }

            throw new InvalidOperationException();
        }
Beispiel #9
0
        protected HqlTreeNode VisitBinaryExpression(BinaryExpression expression)
        {
            var lhs = VisitExpression(expression.Left).AsExpression();
            var rhs = VisitExpression(expression.Right).AsExpression();

            switch (expression.NodeType)
            {
            case ExpressionType.Equal:
                // Need to check for boolean equality
                if (lhs is HqlBooleanExpression || rhs is HqlBooleanExpression)
                {
                    lhs =
                        _hqlTreeBuilder.Case(
                            new [] { _hqlTreeBuilder.When(lhs, _hqlTreeBuilder.Constant(true)) },
                            _hqlTreeBuilder.Constant(false));

                    rhs =
                        _hqlTreeBuilder.Case(
                            new [] { _hqlTreeBuilder.When(rhs, _hqlTreeBuilder.Constant(true)) },
                            _hqlTreeBuilder.Constant(false));

                    return(_hqlTreeBuilder.Equality(lhs, rhs));
                }

                // Check for nulls on left or right.
                if (expression.Right is ConstantExpression &&
                    expression.Right.Type.IsNullableOrReference() &&
                    ((ConstantExpression)expression.Right).Value == null)
                {
                    return(_hqlTreeBuilder.IsNull(lhs));
                }

                if (expression.Left is ConstantExpression &&
                    expression.Left.Type.IsNullableOrReference() &&
                    ((ConstantExpression)expression.Left).Value == null)
                {
                    return(_hqlTreeBuilder.IsNull(rhs));
                }

                // Nothing was null, use standard equality.
                return(_hqlTreeBuilder.Equality(lhs, rhs));

            case ExpressionType.NotEqual:
                // Need to check for boolean in-equality
                if (lhs is HqlBooleanExpression || rhs is HqlBooleanExpression)
                {
                    lhs =
                        _hqlTreeBuilder.Case(
                            new [] { _hqlTreeBuilder.When(lhs, _hqlTreeBuilder.Constant(true)) },
                            _hqlTreeBuilder.Constant(false));

                    rhs =
                        _hqlTreeBuilder.Case(
                            new [] { _hqlTreeBuilder.When(rhs, _hqlTreeBuilder.Constant(true)) },
                            _hqlTreeBuilder.Constant(false));

                    return(_hqlTreeBuilder.Inequality(lhs, rhs));
                }

                // Check for nulls on left or right.
                if (expression.Right is ConstantExpression &&
                    expression.Right.Type.IsNullableOrReference() &&
                    ((ConstantExpression)expression.Right).Value == null)
                {
                    return(_hqlTreeBuilder.IsNotNull(lhs));
                }

                if (expression.Left is ConstantExpression &&
                    expression.Left.Type.IsNullableOrReference() &&
                    ((ConstantExpression)expression.Left).Value == null)
                {
                    return(_hqlTreeBuilder.IsNotNull(rhs));
                }

                // Nothing was null, use standard inequality.
                return(_hqlTreeBuilder.Inequality(lhs, rhs));

            case ExpressionType.And:
                return(_hqlTreeBuilder.BitwiseAnd(lhs, rhs));

            case ExpressionType.AndAlso:
                return(_hqlTreeBuilder.BooleanAnd(lhs.AsBooleanExpression(), rhs.AsBooleanExpression()));

            case ExpressionType.Or:
                return(_hqlTreeBuilder.BitwiseOr(lhs, rhs));

            case ExpressionType.OrElse:
                return(_hqlTreeBuilder.BooleanOr(lhs.AsBooleanExpression(), rhs.AsBooleanExpression()));

            case ExpressionType.Add:
                return(_hqlTreeBuilder.Add(lhs, rhs));

            case ExpressionType.Subtract:
                return(_hqlTreeBuilder.Subtract(lhs, rhs));

            case ExpressionType.Multiply:
                return(_hqlTreeBuilder.Multiply(lhs, rhs));

            case ExpressionType.Divide:
                return(_hqlTreeBuilder.Divide(lhs, rhs));

            case ExpressionType.LessThan:
                return(_hqlTreeBuilder.LessThan(lhs, rhs));

            case ExpressionType.LessThanOrEqual:
                return(_hqlTreeBuilder.LessThanOrEqual(lhs, rhs));

            case ExpressionType.GreaterThan:
                return(_hqlTreeBuilder.GreaterThan(lhs, rhs));

            case ExpressionType.GreaterThanOrEqual:
                return(_hqlTreeBuilder.GreaterThanOrEqual(lhs, rhs));

            case ExpressionType.Coalesce:
                return(_hqlTreeBuilder.Coalesce(lhs, rhs));
            }

            throw new InvalidOperationException();
        }