예제 #1
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));
        }
        protected HqlTreeNode VisitBinaryExpression(BinaryExpression expression)
        {
            var lhs = VisitExpression(expression.Left).AsExpression();
            var rhs = VisitExpression(expression.Right).AsExpression();

            switch (expression.NodeType)
            {
            case ExpressionType.Equal:
                return(TranslateEqualityComparison(expression, lhs, rhs,
                                                   expr => _hqlTreeBuilder.IsNull(expr),
                                                   (l, r) => _hqlTreeBuilder.Equality(l, r)));

            case ExpressionType.NotEqual:
                return(TranslateEqualityComparison(expression, lhs, rhs,
                                                   expr => _hqlTreeBuilder.IsNotNull(expr),
                                                   (l, r) => _hqlTreeBuilder.Inequality(l, r)));

            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:
                if (expression.Left.Type == typeof(string) && expression.Right.Type == typeof(string))
                {
                    return(_hqlTreeBuilder.MethodCall("concat", lhs, rhs));
                }
                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.Modulo:
                return(_hqlTreeBuilder.MethodCall("mod", 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();
        }
예제 #3
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();
        }
예제 #4
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)
                {
                    return(ResolveBooleanEquality(expression, lhs, rhs, (l, r) => _hqlTreeBuilder.Equality(l, r)));
                }

                // 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)
                {
                    return(ResolveBooleanEquality(expression, lhs, rhs, (l, r) => _hqlTreeBuilder.Inequality(l, r)));
                }

                // 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:
                if (expression.Left.Type == typeof(string) && expression.Right.Type == typeof(string))
                {
                    return(_hqlTreeBuilder.MethodCall("concat", lhs, rhs));
                }
                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.Modulo:
                return(_hqlTreeBuilder.MethodCall("mod", 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();
        }
 /// <summary>
 /// Overrides the BuildHql method to add an expression that supports Linq querying using the supported methods.
 /// </summary>
 public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection <Expression> arguments,
                                      HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
 {
     return(treeBuilder.IsNotNull(visitor.Visit(arguments[0]).AsExpression()));
 }