예제 #1
0
        private static string GetBinOpString(ODataBinaryOp op)
        {
            switch (op)
            {
            case ODataBinaryOp.Add: return("+");

            case ODataBinaryOp.And: return("AND");

            case ODataBinaryOp.Divide: return("/");

            case ODataBinaryOp.Equal: return("=");

            case ODataBinaryOp.GreaterThan: return(">");

            case ODataBinaryOp.GreaterThanOrEqual: return(">=");

            case ODataBinaryOp.LessThan: return("<");

            case ODataBinaryOp.LessThanOrEqual: return("<=");

            case ODataBinaryOp.Modulo: throw new InvalidOperationException("Modulo is handled separately!");

            case ODataBinaryOp.Multiply: return("*");

            // ansii standard, see http://blog.sqlauthority.com/2013/07/08/sql-difference-between-and-operator-used-for-not-equal-to-operation/
            case ODataBinaryOp.NotEqual: return("<>");

            case ODataBinaryOp.Or: return("OR");

            case ODataBinaryOp.Subtract: return("-");

            default: throw Throw.UnexpectedCase(op);
            }
        }
 internal ODataBinaryOpExpression(ODataExpression left, ODataBinaryOp @operator, ODataExpression right, Type clrType)
     : base(ODataExpressionKind.BinaryOp, clrType.ToODataExpressionType(), clrType)
 {
     Throw<ArgumentException>.If(right.Type != left.Type, "right & left: must have equal types");
     this.Right = right;
     this.Operator = @operator;
     this.Left = left;
 }
예제 #3
0
        internal ODataBinaryOpExpression(ODataExpression left, ODataBinaryOp @operator, ODataExpression right, Type clrType)
            : base(ODataExpressionKind.BinaryOp, clrType.ToODataExpressionType(), clrType)
        {
            Throw <ArgumentException> .If(right.Type != left.Type, "right & left: must have equal types");

            this.Right    = right;
            this.Operator = @operator;
            this.Left     = left;
        }
예제 #4
0
        private static Type GetCanonicalArgumentType(ODataBinaryOp @operator)
        {
            switch (@operator)
            {
            case ODataBinaryOp.Add:
            case ODataBinaryOp.Subtract:
            case ODataBinaryOp.Multiply:
            case ODataBinaryOp.Divide:
            case ODataBinaryOp.Modulo:
                // the reason for this is that int can be cast implicitly to most of the other primitive types,
                // so an expression like substring('foo', A add B) will work if A and B are integers
                // alternatively, we could return Unknown for these
                return(typeof(int?));

            case ODataBinaryOp.And:
            case ODataBinaryOp.Or:
                return(typeof(bool));

            default:
                return(typeof(ODataObject));
            }
        }
 private ODataExpression TranslateBinary(Expression linq, ODataBinaryOp op)
 {
     var binary = (BinaryExpression)linq;
     return ODataExpression.BinaryOp(this.TranslateInternal(binary.Left), op, this.TranslateInternal(binary.Right));
 }
예제 #6
0
        private ODataExpression TranslateBinary(Expression linq, ODataBinaryOp op)
        {
            var binary = (BinaryExpression)linq;

            return(ODataExpression.BinaryOp(this.TranslateInternal(binary.Left), op, this.TranslateInternal(binary.Right)));
        }
예제 #7
0
        internal static ODataBinaryOpExpression BinaryOp(ODataExpression left, ODataBinaryOp @operator, ODataExpression right)
        {
            Throw.IfNull(left, "left");
            Throw.IfNull(right, "right");

            // add in implicit conversions as needed
            ODataExpression convertedLeft, convertedRight;

            if ((left.Type == ODataExpressionType.Unknown || left.Type == ODataExpressionType.Null) &&
                (right.Type == ODataExpressionType.Unknown || right.Type == ODataExpressionType.Null))
            {
                var canonicalType = GetCanonicalArgumentType(@operator);
                if (canonicalType != typeof(ODataObject))
                {
                    convertedLeft = left.Type == ODataExpressionType.Unknown
                        ? ConvertFromUnknownType(left, canonicalType)
                        : LiftNullToUnknown(left);
                    convertedRight = right.Type == ODataExpressionType.Unknown
                        ? ConvertFromUnknownType(right, canonicalType)
                        : LiftNullToUnknown(right);
                }
                else
                {
                    convertedLeft  = left.Type == ODataExpressionType.Null ? LiftNullToUnknown(left) : left;
                    convertedRight = right.Type == ODataExpressionType.Null ? LiftNullToUnknown(right) : right;
                }
            }
            else if (left.Type == ODataExpressionType.Unknown)
            {
                convertedLeft  = ConvertFromUnknownType(left, right.ClrType);
                convertedRight = right;
            }
            else if (right.Type == ODataExpressionType.Unknown)
            {
                convertedLeft  = left;
                convertedRight = ConvertFromUnknownType(right, left.ClrType);;
            }
            else if (left.Type == right.Type)
            {
                convertedLeft  = left;
                convertedRight = right;
            }
            else if (left.Type.IsImplicityCastableTo(right.Type))
            {
                convertedLeft  = Convert(left, right.ClrType);
                convertedRight = right;
            }
            else if (right.Type.IsImplicityCastableTo(left.Type))
            {
                convertedLeft  = left;
                convertedRight = Convert(right, left.ClrType);
            }
            else
            {
                throw new ArgumentException(string.Format("Operator {0} cannot be applied to operands of type '{1}' and '{2}'", @operator, left.Type, right.Type));
            }

            // determine the result type
            var  operandClrType = convertedLeft.ClrType;
            var  operandType    = convertedLeft.Type;
            Type resultClrType;

            switch (@operator)
            {
            case ODataBinaryOp.Add:
            case ODataBinaryOp.Subtract:
            case ODataBinaryOp.Multiply:
            case ODataBinaryOp.Divide:
            case ODataBinaryOp.Modulo:
                Throw.If(!operandType.IsNumeric(), "Operator requires numeric type");
                resultClrType = operandClrType;
                break;

            case ODataBinaryOp.LessThan:
            case ODataBinaryOp.LessThanOrEqual:
            case ODataBinaryOp.GreaterThanOrEqual:
            case ODataBinaryOp.GreaterThan:
                Throw.If(
                    !operandType.IsNumeric() && !NonNumericComparableTypes.Contains(operandType) && operandType != ODataExpressionType.Unknown,
                    "Operator requires a type with comparison operators defined"
                    );
                resultClrType = typeof(bool);
                break;

            case ODataBinaryOp.And:
            case ODataBinaryOp.Or:
                Throw.If(operandClrType != typeof(bool), "Boolean operators require operands with a non-nullable boolean type");
                resultClrType = typeof(bool);
                break;

            case ODataBinaryOp.Equal:
            case ODataBinaryOp.NotEqual:
                resultClrType = typeof(bool);
                break;

            default:
                throw Throw.UnexpectedCase(@operator);
            }

            // construct the expression
            return(new ODataBinaryOpExpression(convertedLeft, @operator, convertedRight, resultClrType));
        }
예제 #8
0
        internal static ODataBinaryOpExpression BinaryOp(ODataExpression left, ODataBinaryOp @operator, ODataExpression right)
        {
            Throw.IfNull(left, "left");
            Throw.IfNull(right, "right");

            // add in implicit conversions as needed
            ODataExpression convertedLeft, convertedRight;
            if (left.Type == right.Type)
            {
                convertedLeft = left;
                convertedRight = right;
            }
            else if (left.Type.IsImplicityCastableTo(right.Type))
            {
                convertedLeft = Convert(left, right.ClrType);
                convertedRight = right;
            }
            else if (right.Type.IsImplicityCastableTo(left.Type))
            {
                convertedLeft = left;
                convertedRight = Convert(right, left.ClrType);
            }
            else
            {
                throw new ArgumentException(string.Format("Types {0} and {1} cannot be used with operator {2}", left.Type, right.Type, @operator));
            }

            // determine the result type
            var operandClrType = convertedLeft.ClrType;
            var operandType = convertedLeft.Type;
            Type resultClrType;
            switch (@operator)
            {
                case ODataBinaryOp.Add:
                case ODataBinaryOp.Subtract:
                case ODataBinaryOp.Multiply:
                case ODataBinaryOp.Divide:
                case ODataBinaryOp.Modulo:
                    Throw.If(!operandType.IsNumeric(), "Operator requires numeric type");
                    resultClrType = operandClrType;
                    break;
                case ODataBinaryOp.LessThan:
                case ODataBinaryOp.LessThanOrEqual:
                case ODataBinaryOp.GreaterThanOrEqual:
                case ODataBinaryOp.GreaterThan:
                    Throw.If(!operandType.IsNumeric() && !NonNumericComparableTypes.Contains(operandType), "Operator requires a type with comparison operators defined");
                    resultClrType = typeof(bool);
                    break;
                case ODataBinaryOp.And:
                case ODataBinaryOp.Or:
                    Throw.If(operandClrType != typeof(bool), "Boolean operators require operands with a non-nullable boolean type");
                    resultClrType = typeof(bool);
                    break;
                case ODataBinaryOp.Equal:
                case ODataBinaryOp.NotEqual:
                    resultClrType = typeof(bool);
                    break;
                default:
                    throw Throw.UnexpectedCase(@operator);
            }

            // construct the expression
            return new ODataBinaryOpExpression(convertedLeft, @operator, convertedRight, resultClrType);
        }