示例#1
0
 private static SqlExpression GenericStringIndexOf(SqlExpression _this,
                                                   SqlExpression substring, SqlExpression startIndex, SqlExpression length)
 {
     return(SqlDml.Coalesce(startIndex +
                            SqlDml.NullIf(SqlDml.Position(substring, SqlDml.Substring(_this, startIndex, length)), -1),
                            -1));
 }
        public static SqlExpression NullableGetValueOrDefault(MemberInfo memberInfo, SqlExpression _this, SqlExpression _default)
        {
            var          context   = ExpressionTranslationContext.Current;
            var          @this     = _this;
            var          @default  = _default;
            SqlContainer container = @this as SqlContainer;

            if (container != null)
            {
                if (container.Value.GetType().IsEnum)
                {
                    @this = SqlDml.Literal(Convert.ChangeType(container.Value, Enum.GetUnderlyingType(container.Value.GetType())));
                }
            }
            container = @default as SqlContainer;
            if (container != null)
            {
                if (container.Value.GetType().IsEnum)
                {
                    @default = SqlDml.Literal(Convert.ChangeType(container.Value, Enum.GetUnderlyingType(container.Value.GetType())));
                }
            }
            if (!IsBooleanSpecialCase(context, memberInfo))
            {
                return(SqlDml.Coalesce(@this, @default));
            }
            return(context.BooleanExpressionConverter.IntToBoolean(SqlDml.Coalesce(
                                                                       context.BooleanExpressionConverter.BooleanToInt(@this),
                                                                       context.BooleanExpressionConverter.BooleanToInt(@default))));
        }
        public static SqlExpression NullableGetValueOrDefault(MemberInfo memberInfo, SqlExpression _this)
        {
            var context      = ExpressionTranslationContext.Current;
            var defaultValue = SqlDml.Literal(Activator.CreateInstance(memberInfo.DeclaringType.StripNullable()));

            if (!IsBooleanSpecialCase(context, memberInfo))
            {
                return(SqlDml.Coalesce(_this, defaultValue));
            }
            return(context.BooleanExpressionConverter.IntToBoolean(
                       SqlDml.Coalesce(context.BooleanExpressionConverter.BooleanToInt(_this), defaultValue)));
        }
        protected override SqlExpression VisitBinary(BinaryExpression expression)
        {
            // handle x.CompareTo(y) > 0 and similar comparisons
            SqlExpression result = TryTranslateCompareExpression(expression);

            if (!result.IsNullReference())
            {
                return(result);
            }

            SqlExpression left;
            SqlExpression right;

            bool isEqualityCheck =
                expression.NodeType == ExpressionType.Equal ||
                expression.NodeType == ExpressionType.NotEqual;

            bool isBooleanFixRequired = fixBooleanExpressions &&
                                        (isEqualityCheck || expression.NodeType == ExpressionType.Coalesce) &&
                                        (IsBooleanExpression(expression.Left) || IsBooleanExpression(expression.Right));

            if (IsCharToIntConvert(expression.Left) && IsCharToIntConvert(expression.Right))
            {
                // chars are compared as integers, but we store them as strings and should compare them like strings.
                left  = Visit(GetOperand(expression.Left), isEqualityCheck);
                right = Visit(GetOperand(expression.Right), isEqualityCheck);
            }
            else if (IsCharToIntConvert(expression.Left) && IsIntConstant(expression.Right))
            {
                // another case of char comparison
                left  = Visit(GetOperand(expression.Left), isEqualityCheck);
                right = ConvertIntConstantToSingleCharString(expression.Right);
            }
            else if (IsIntConstant(expression.Left) && IsCharToIntConvert(expression.Right))
            {
                // another case of char comparison
                left  = ConvertIntConstantToSingleCharString(expression.Left);
                right = Visit(GetOperand(expression.Right), isEqualityCheck);
            }
            else
            {
                // regular case
                left  = Visit(expression.Left, isEqualityCheck);
                right = Visit(expression.Right, isEqualityCheck);
            }
            if (isBooleanFixRequired)
            {
                // boolean expressions should be compared as integers.
                // additional check is required because some type information might be lost.
                // we assume they already have correct format in that case.
                if (IsBooleanExpression(expression.Left))
                {
                    left = booleanExpressionConverter.BooleanToInt(left);
                }
                if (IsBooleanExpression(expression.Right))
                {
                    right = booleanExpressionConverter.BooleanToInt(right);
                }
            }

            //handle SQLite DateTime comparsion
            if (dateTimeEmulation &&
                left.NodeType != SqlNodeType.Null &&
                right.NodeType != SqlNodeType.Null &&
                IsComparisonExpression(expression) &&
                (IsDateTimeExpression(expression.Left) || IsDateTimeExpression(expression.Right)))
            {
                left  = SqlDml.Cast(left, SqlType.DateTime);
                right = SqlDml.Cast(right, SqlType.DateTime);
            }

            //handle SQLite DateTimeOffset comparsion
            if (dateTimeOffsetEmulation &&
                left.NodeType != SqlNodeType.Null &&
                right.NodeType != SqlNodeType.Null &&
                IsComparisonExpression(expression) &&
                (IsDateTimeOffsetExpression(expression.Left) || IsDateTimeOffsetExpression(expression.Right)))
            {
                left  = SqlDml.Cast(left, SqlType.DateTimeOffset);
                right = SqlDml.Cast(right, SqlType.DateTimeOffset);
            }

            // handle special cases
            result = TryTranslateBinaryExpressionSpecialCases(expression, left, right);
            if (!result.IsNullReference())
            {
                return(result);
            }

            // handle overloaded operators
            if (expression.Method != null)
            {
                return(CompileMember(expression.Method, null, left, right));
            }

            //handle wrapped enums
            SqlContainer container = left as SqlContainer;

            if (container != null)
            {
                left = TryUnwrapEnum(container);
            }
            container = right as SqlContainer;
            if (container != null)
            {
                right = TryUnwrapEnum(container);
            }

            switch (expression.NodeType)
            {
            case ExpressionType.Add:
            case ExpressionType.AddChecked:
                return(SqlDml.Add(left, right));

            case ExpressionType.And:
                return(IsBooleanExpression(expression.Left)
          ? SqlDml.And(left, right)
          : SqlDml.BitAnd(left, right));

            case ExpressionType.AndAlso:
                return(SqlDml.And(left, right));

            case ExpressionType.Coalesce:
                SqlExpression coalesce = SqlDml.Coalesce(left, right);
                if (isBooleanFixRequired)
                {
                    coalesce = booleanExpressionConverter.IntToBoolean(coalesce);
                }
                return(coalesce);

            case ExpressionType.Divide:
                return(SqlDml.Divide(left, right));

            case ExpressionType.Equal:
                return(SqlDml.Equals(left, right));

            case ExpressionType.ExclusiveOr:
                return(SqlDml.BitXor(left, right));

            case ExpressionType.GreaterThan:
                return(SqlDml.GreaterThan(left, right));

            case ExpressionType.GreaterThanOrEqual:
                return(SqlDml.GreaterThanOrEquals(left, right));

            case ExpressionType.LessThan:
                return(SqlDml.LessThan(left, right));

            case ExpressionType.LessThanOrEqual:
                return(SqlDml.LessThanOrEquals(left, right));

            case ExpressionType.Modulo:
                return(SqlDml.Modulo(left, right));

            case ExpressionType.Multiply:
            case ExpressionType.MultiplyChecked:
                return(SqlDml.Multiply(left, right));

            case ExpressionType.NotEqual:
                return(SqlDml.NotEquals(left, right));

            case ExpressionType.Or:
                return(IsBooleanExpression(expression.Left)
          ? SqlDml.Or(left, right)
          : SqlDml.BitOr(left, right));

            case ExpressionType.OrElse:
                return(SqlDml.Or(left, right));

            case ExpressionType.Subtract:
            case ExpressionType.SubtractChecked:
                return(SqlDml.Subtract(left, right));

            default:
                throw new ArgumentOutOfRangeException("expression");
            }
        }
示例#5
0
        public override void Visit(SqlFunctionCall node)
        {
            switch (node.FunctionType)
            {
            case SqlFunctionType.PadLeft:
            case SqlFunctionType.PadRight:
                SqlHelper.GenericPad(node).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeOffsetAddYears:
            case SqlFunctionType.DateTimeAddYears:
                DateTimeAddComponent(node.Arguments[0], node.Arguments[1], true).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeOffsetAddMonths:
            case SqlFunctionType.DateTimeAddMonths:
                DateTimeAddComponent(node.Arguments[0], node.Arguments[1], false).AcceptVisitor(this);
                return;

            case SqlFunctionType.IntervalConstruct:
                IntervalConstruct(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeConstruct:
                DateTimeConstruct(node.Arguments[0], node.Arguments[1], node.Arguments[2]).AcceptVisitor(this);
                return;

            case SqlFunctionType.IntervalAbs:
                SqlHelper.IntervalAbs(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.IntervalToMilliseconds:
                SqlHelper.IntervalToMilliseconds(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.IntervalToNanoseconds:
                SqlHelper.IntervalToNanoseconds(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.Position:
                Position(node.Arguments[0], node.Arguments[1]).AcceptVisitor(this);
                return;

            case SqlFunctionType.CharLength:
                SqlDml.Coalesce(SqlDml.FunctionCall("LENGTH", node.Arguments[0]), 0).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeToStringIso:
                DateTimeToStringIso(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeOffsetConstruct:
                DateTimeOffsetConstruct(node.Arguments[0], node.Arguments[1]).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeOffsetTimeOfDay:
                DateTimeOffsetTimeOfDay(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeOffsetToLocalTime:
                DateTimeOffsetToLocalTime(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeToDateTimeOffset:
                DateTimeToDateTimeOffset(node.Arguments[0]).AcceptVisitor(this);
                return;

            case SqlFunctionType.DateTimeOffsetToUtcTime:
                DateTimeOffsetToUtcTime(node.Arguments[0]).AcceptVisitor(this);
                return;

            default:
                base.Visit(node);
                return;
            }
        }