예제 #1
0
        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).Equals(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);
            }

            //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.Constant(true)) }, _hqlTreeBuilder.Constant(false)));
        }
예제 #2
0
        protected HqlTreeNode VisitNhSum(NhSumExpression expression)
        {
            var sum      = _hqlTreeBuilder.Sum(VisitExpression(expression.Expression).AsExpression());
            var cast     = _hqlTreeBuilder.Cast(sum, expression.Type);
            var coalesce = _hqlTreeBuilder.Coalesce(cast, _hqlTreeBuilder.Constant(0));

            return(coalesce);
        }
예제 #3
0
 public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection <Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
 {
     return(treeBuilder.Like(
                visitor.Visit(targetObject).AsExpression(),
                treeBuilder.Concat(
                    treeBuilder.Constant("%"),
                    visitor.Visit(arguments[0]).AsExpression(),
                    treeBuilder.Constant("%"))));
 }
예제 #4
0
        protected HqlTreeNode VisitConstantExpression(ConstantExpression expression)
        {
            if (expression.Value != null)
            {
                IEntityNameProvider entityName = expression.Value as IEntityNameProvider;
                if (entityName != null)
                {
                    return(_hqlTreeBuilder.Ident(entityName.EntityName));
                }
            }

            NamedParameter namedParameter;

            if (_parameters.ConstantToParameterMap.TryGetValue(expression, out namedParameter))
            {
                _parameters.RequiredHqlParameters.Add(new NamedParameterDescriptor(namedParameter.Name, null, false));
                var parameter = _hqlTreeBuilder.Parameter(namedParameter.Name).AsExpression();

                // SQLite driver binds decimal parameters to text, which can cause unexpected results in arithmetic operations.
                return(_parameters.SessionFactory.Dialect.IsDecimalStoredAsFloatingPointNumber && expression.Type.UnwrapIfNullable() == typeof(decimal)
                                        ? _hqlTreeBuilder.TransparentCast(parameter, expression.Type)
                                        : parameter);
            }

            return(_hqlTreeBuilder.Constant(expression.Value));
        }
예제 #5
0
        public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection <Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            string trimWhere;

            if (method.Name == "TrimStart")
            {
                trimWhere = "leading";
            }
            else if (method.Name == "TrimEnd")
            {
                trimWhere = "trailing";
            }
            else
            {
                trimWhere = "both";
            }

            var trimChars = ExtractTrimChars(arguments);

            if (string.IsNullOrEmpty(trimChars))
            {
                return(treeBuilder.MethodCall("trim", treeBuilder.Ident(trimWhere), treeBuilder.Ident("from"), visitor.Visit(targetObject).AsExpression()));
            }
            else
            {
                return(treeBuilder.MethodCall("trim", treeBuilder.Ident(trimWhere), treeBuilder.Constant(trimChars), treeBuilder.Ident("from"), visitor.Visit(targetObject).AsExpression()));
            }
        }
        public override HqlTreeNode BuildHql(
            MethodInfo method,
            Expression targetObject,
            ReadOnlyCollection <Expression> arguments,
            HqlTreeBuilder treeBuilder,
            IHqlExpressionVisitor visitor)
        {
            var left  = treeBuilder.Cast(visitor.Visit(targetObject).AsExpression(), typeof(string));
            var right = treeBuilder.Cast(visitor.Visit(arguments.First()).AsExpression(), typeof(string));

            var leftSubstring  = treeBuilder.MethodCall("substring", left, treeBuilder.Constant(4));
            var rightSubstring = treeBuilder.MethodCall("substring", right, treeBuilder.Constant(4));
            var equals         = treeBuilder.Equality(leftSubstring, rightSubstring);

            return(equals);
        }
예제 #7
0
        public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection <Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            var argsCount = arguments.Count;

            if (LogIgnoredStringComparisonParameter(method, MethodWithComparer1, MethodWithComparer2))
            {
                //StringComparison is last argument, just ignore it
                argsCount--;
            }

            HqlMethodCall locate;

            if (argsCount == 1)
            {
                locate = treeBuilder.MethodCall("locate",
                                                visitor.Visit(arguments[0]).AsExpression(),
                                                visitor.Visit(targetObject).AsExpression()); //,
                //treeBuilder.Constant(0));
            }
            else
            {
                var start = treeBuilder.Add(visitor.Visit(arguments[1]).AsExpression(), treeBuilder.Constant(1));
                locate = treeBuilder.MethodCall("locate",
                                                visitor.Visit(arguments[0]).AsExpression(),
                                                visitor.Visit(targetObject).AsExpression(),
                                                start);
            }
            return(treeBuilder.Subtract(locate, treeBuilder.Constant(1)));
        }
예제 #8
0
        public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection <Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            var expression = visitor.Visit(targetObject).AsExpression();
            var index      = treeBuilder.Add(visitor.Visit(arguments[0]).AsExpression(), treeBuilder.Constant(1));

            return(treeBuilder.MethodCall("substring", expression, index, treeBuilder.Constant(1)));
        }
예제 #9
0
        private HqlTreeNode BuildFromArray(Array valueArray, HqlTreeBuilder treeBuilder)
        {
            var elementType = valueArray.GetType().GetElementType();

            if (!elementType.IsValueType && elementType != typeof(string))
            {
                throw new ArgumentException("Only primitives and strings can be used");
            }

            Type enumUnderlyingType = elementType.IsEnum ? Enum.GetUnderlyingType(elementType) : null;
            var  variants           = new HqlExpression[valueArray.Length];

            for (int index = 0; index < valueArray.Length; index++)
            {
                var variant = valueArray.GetValue(index);
                var val     = variant;

                if (elementType.IsEnum)
                {
                    val = Convert.ChangeType(variant, enumUnderlyingType);
                }

                variants[index] = treeBuilder.Constant(val);
            }

            return(treeBuilder.ExpressionSubTreeHolder(variants));
        }
예제 #10
0
 public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection <Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
 {
     LogIgnoredStringComparisonParameter(method, MethodWithComparer);
     return(treeBuilder.Like(
                visitor.Visit(targetObject).AsExpression(),
                treeBuilder.Concat(
                    visitor.Visit(arguments[0]).AsExpression(),
                    treeBuilder.Constant("%"))));
 }
        public override HqlExpression BuildHql(HqlExpression expression, ReadOnlyCollection <HqlExpression> arguments, HqlTreeBuilder treeBuilder)
        {
            HqlExpression factor = treeBuilder.Constant(_factor);

            if (_transformer != null)
            {
                return(treeBuilder.Multiply(treeBuilder.Cast(_transformer.BuildHql(expression, arguments, treeBuilder), typeof(long)), factor));
            }
            return(treeBuilder.Multiply(treeBuilder.Cast(expression, typeof(long)), factor));
        }
예제 #12
0
        public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection <Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            var numberOfDecimals = arguments.Count == 2
                                ? visitor.Visit(arguments[1]).AsExpression()
                                : treeBuilder.Constant(0);

            return(treeBuilder.TransparentCast(
                       treeBuilder.MethodCall("round", visitor.Visit(arguments[0]).AsExpression(), numberOfDecimals),
                       method.ReturnType));
        }
        private static HqlExpression GetRhs(MethodInfo method, ReadOnlyCollection <Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            if (arguments.Count > 0)
            {
                return(visitor.Visit(arguments[0]).ToArithmeticExpression());
            }

            var returnType = method.ReturnType;
            var instance   = returnType.IsValueType ? Activator.CreateInstance(returnType) : null;

            return(treeBuilder.Constant(instance));
        }
예제 #14
0
        public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection <Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            if (arguments.Count == 1)
            {
                return(treeBuilder.MethodCall("substring", visitor.Visit(targetObject).AsExpression(),
                                              treeBuilder.Constant(0),
                                              visitor.Visit(arguments[0]).AsExpression()));
            }

            return(treeBuilder.MethodCall("substring", visitor.Visit(targetObject).AsExpression(),
                                          visitor.Visit(arguments[0]).AsExpression(),
                                          visitor.Visit(arguments[1]).AsExpression()));
        }
예제 #15
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)));
        }
예제 #16
0
        public override HqlTreeNode BuildHql(
            MethodInfo method,
            Expression targetObject,
            ReadOnlyCollection <Expression> arguments,
            HqlTreeBuilder treeBuilder,
            IHqlExpressionVisitor visitor)
        {
            if (method == _nextDouble)
            {
                return(treeBuilder.MethodCall(_randomFunctionName));
            }

            switch (arguments.Count)
            {
            case 0:
                return(treeBuilder.Cast(
                           treeBuilder.MethodCall(
                               _floorFunctionName,
                               treeBuilder.Multiply(
                                   treeBuilder.MethodCall(_randomFunctionName),
                                   treeBuilder.Constant(int.MaxValue))),
                           typeof(int)));

            case 1:
                return(treeBuilder.Cast(
                           treeBuilder.MethodCall(
                               _floorFunctionName,
                               treeBuilder.Multiply(
                                   treeBuilder.MethodCall(_randomFunctionName),
                                   visitor.Visit(arguments[0]).AsExpression())),
                           typeof(int)));

            case 2:
                var minValue = visitor.Visit(arguments[0]).AsExpression();
                var maxValue = visitor.Visit(arguments[1]).AsExpression();
                return(treeBuilder.Cast(
                           treeBuilder.Add(
                               treeBuilder.MethodCall(
                                   _floorFunctionName,
                                   treeBuilder.Multiply(
                                       treeBuilder.MethodCall(_randomFunctionName),
                                       treeBuilder.Subtract(maxValue, minValue))),
                               minValue),
                           typeof(int)));

            default:
                throw new NotSupportedException();
            }
        }
예제 #17
0
 public HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection <Expression> arguments,
                             HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
 {
     if (arguments.Count == 2)
     {
         return(treeBuilder.Like(
                    visitor.Visit(arguments[0]).AsExpression(),
                    visitor.Visit(arguments[1]).AsExpression()));
     }
     if (arguments[2].NodeType == ExpressionType.Constant)
     {
         var escapeCharExpression = (ConstantExpression)arguments[2];
         return(treeBuilder.Like(
                    visitor.Visit(arguments[0]).AsExpression(),
                    visitor.Visit(arguments[1]).AsExpression(),
                    treeBuilder.Constant(escapeCharExpression.Value)));
     }
     throw new ArgumentException("The escape character must be specified as literal value or a string variable");
 }
예제 #18
0
        private HqlTreeNode BuildFromArray(IEnumerable valueArray, HqlTreeBuilder treeBuilder, Type elementType)
        {
            Type enumUnderlyingType      = elementType.IsEnum ? Enum.GetUnderlyingType(elementType) : null;
            IList <HqlTreeNode> variants = new List <HqlTreeNode>();

            foreach (object variant in valueArray)
            {
                object val = variant;

                if (elementType.IsEnum)
                {
                    val = Convert.ChangeType(variant, enumUnderlyingType);
                }

                HqlConstant hqlConstant = treeBuilder.Constant(val);
                variants.Add(hqlConstant);
            }

            return(treeBuilder.ExpressionSubTreeHolder(variants));
        }
예제 #19
0
        public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection <Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            HqlMethodCall locate;

            if (arguments.Count == 1)
            {
                locate = treeBuilder.MethodCall("locate",
                                                visitor.Visit(arguments[0]).AsExpression(),
                                                visitor.Visit(targetObject).AsExpression()); //,
                //treeBuilder.Constant(0));
            }
            else
            {
                var start = treeBuilder.Add(visitor.Visit(arguments[1]).AsExpression(), treeBuilder.Constant(1));
                locate = treeBuilder.MethodCall("locate",
                                                visitor.Visit(arguments[0]).AsExpression(),
                                                visitor.Visit(targetObject).AsExpression(),
                                                start);
            }
            return(treeBuilder.Subtract(locate, treeBuilder.Constant(1)));
        }
예제 #20
0
        protected HqlTreeNode VisitConstantExpression(ConstantExpression expression)
        {
            if (expression.Value != null)
            {
                IEntityNameProvider entityName = expression.Value as IEntityNameProvider;
                if (entityName != null)
                {
                    return(_hqlTreeBuilder.Ident(entityName.EntityName));
                }
            }

            NamedParameter namedParameter;

            if (_parameters.ConstantToParameterMap.TryGetValue(expression, out namedParameter))
            {
                _parameters.RequiredHqlParameters.Add(new NamedParameterDescriptor(namedParameter.Name, null, false));

                return(_hqlTreeBuilder.Parameter(namedParameter.Name).AsExpression());
            }

            return(_hqlTreeBuilder.Constant(expression.Value));
        }
예제 #21
0
        public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection <Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            string trimWhere;

            if (method.Name == "TrimStart")
            {
                trimWhere = "leading";
            }
            else if (method.Name == "TrimEnd")
            {
                trimWhere = "trailing";
            }
            else
            {
                trimWhere = "both";
            }

            string trimChars = "";

            if (method.GetParameters().Length > 0)
            {
                foreach (char c in (char[])((ConstantExpression)arguments[0]).Value)
                {
                    trimChars += c;
                }
            }


            if (trimChars == "")
            {
                return(treeBuilder.MethodCall("trim", treeBuilder.Ident(trimWhere), treeBuilder.Ident("from"), visitor.Visit(targetObject).AsExpression()));
            }
            else
            {
                return(treeBuilder.MethodCall("trim", treeBuilder.Ident(trimWhere), treeBuilder.Constant(trimChars), treeBuilder.Ident("from"), visitor.Visit(targetObject).AsExpression()));
            }
        }
예제 #22
0
 public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection <Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
 {
     return(treeBuilder.Constant(1));
 }
예제 #23
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();
        }
예제 #24
0
 public override HqlTreeNode BuildHql(MethodInfo method, Expression expression, ReadOnlyCollection <Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
 {
     return(treeBuilder.MethodCall("truncate", visitor.Visit(arguments[0]).AsExpression(), treeBuilder.Constant(0)));
 }
예제 #25
0
        public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection <Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            var stringExpr = visitor.Visit(targetObject).AsExpression();
            var start      = treeBuilder.Add(visitor.Visit(arguments[0]).AsExpression(), treeBuilder.Constant(1));

            if (arguments.Count == 1)
            {
                return(treeBuilder.MethodCall("substring", stringExpr, start));
            }

            var length = visitor.Visit(arguments[1]).AsExpression();

            return(treeBuilder.MethodCall("substring", stringExpr, start, length));
        }
예제 #26
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();
        }
예제 #27
0
 public override HqlExpression Convert(HqlTreeBuilder treeBuilder, HqlExpression input)
 {
     return(treeBuilder.Multiply(input, treeBuilder.Constant(_factor)));
 }