/// <summary>
 /// Do the specified BinaryOperation for the two values and returns the result.
 /// </summary>
 /// <param name="operation">The binary operation to perform.</param>
 /// <param name="firstValue">The first value.</param>
 /// <param name="secondValue">The second value.</param>
 /// <returns>
 /// Result of the operation.
 /// </returns>
 public override QueryScalarValue Evaluate(QueryBinaryOperation operation, QueryScalarValue firstValue, QueryScalarValue secondValue)
 {
     if (operation == QueryBinaryOperation.LessThan || operation == QueryBinaryOperation.LessThanOrEqualTo)
     {
         return this.PerformNullSafeLessThan(firstValue, secondValue, operation);
     }
     
     return base.Evaluate(operation, firstValue, secondValue);
 }
Example #2
0
        /// <summary>
        /// Determines whether a typed data can do certain operation with another typed data
        /// </summary>
        /// <param name="operation">the operation</param>
        /// <param name="sourceType">the type of data to operation on</param>
        /// <param name="otherType">the other type</param>
        /// <returns>Value <c>true</c> if operation can be performed; otherwise, <c>false</c>.</returns>
        public override bool Supports(QueryBinaryOperation operation, QueryScalarType sourceType, QueryScalarType otherType)
        {
            if (this.IsSpatialType((IQueryClrType)sourceType) || this.IsSpatialType((IQueryClrType)otherType))
            {
                return(false);
            }

            return(base.Supports(operation, sourceType, otherType));
        }
        /// <summary>
        /// Determines whether a typed data can do certain operation with another typed data
        /// </summary>
        /// <param name="operation">the operation</param>
        /// <param name="sourceType">the type of data to operation on</param>
        /// <param name="otherType">the other type</param>
        /// <returns>Value <c>true</c> if operation can be performed; otherwise, <c>false</c>.</returns>
        public virtual bool Supports(QueryBinaryOperation operation, QueryScalarType sourceType, QueryScalarType otherType)
        {
            var sourceQueryClrType = (IQueryClrType)sourceType;
            var otherQueryClrType  = (IQueryClrType)otherType;
            var sourceClrType      = sourceQueryClrType.ClrType;
            var otherClrType       = otherQueryClrType.ClrType;

            switch (operation)
            {
            case QueryBinaryOperation.Add:
            case QueryBinaryOperation.Divide:
            case QueryBinaryOperation.Modulo:
            case QueryBinaryOperation.Multiply:
            case QueryBinaryOperation.Subtract:
                return(LinqTypeSemantics.IsNumeric(sourceClrType) &&
                       LinqTypeSemantics.IsNumeric(otherClrType) &&
                       this.HaveCommonType(sourceClrType, otherClrType));

            case QueryBinaryOperation.BitwiseAnd:
            case QueryBinaryOperation.BitwiseExclusiveOr:
            case QueryBinaryOperation.BitwiseOr:
                return(LinqTypeSemantics.IsIntegralType(sourceClrType) &&
                       LinqTypeSemantics.IsIntegralType(otherClrType) &&
                       this.HaveCommonType(sourceClrType, otherClrType));

            case QueryBinaryOperation.LogicalAnd:
            case QueryBinaryOperation.LogicalOr:
                return(sourceClrType == typeof(bool) && otherClrType == typeof(bool));

            case QueryBinaryOperation.EqualTo:
            case QueryBinaryOperation.NotEqualTo:
                return(this.HaveCommonType(sourceClrType, otherClrType));

            case QueryBinaryOperation.LessThan:
            case QueryBinaryOperation.LessThanOrEqualTo:
            case QueryBinaryOperation.GreaterThan:
            case QueryBinaryOperation.GreaterThanOrEqualTo:
                if (sourceClrType == typeof(byte[]) || otherClrType == typeof(byte[]) ||
                    sourceClrType == typeof(string) || otherClrType == typeof(string) ||
                    sourceClrType == typeof(bool) || otherClrType == typeof(bool) ||
                    sourceClrType == typeof(bool?) || otherClrType == typeof(bool?) ||
                    this.IsSpatialType(sourceQueryClrType) || this.IsSpatialType(otherQueryClrType))
                {
                    return(false);
                }
                else
                {
                    return(this.HaveCommonType(sourceClrType, otherClrType));
                }

            case QueryBinaryOperation.Concat:
                return(sourceClrType == typeof(string) || otherClrType == typeof(string));

            default:
                throw new TaupoNotSupportedException("Unsupported query binary operation.");
            }
        }
Example #4
0
        /// <summary>
        /// Do the specified BinaryOperation for the two values and returns the result.
        /// </summary>
        /// <param name="operation">The binary operation to perform.</param>
        /// <param name="firstValue">The first value.</param>
        /// <param name="secondValue">The second value.</param>
        /// <returns>
        /// Result of the operation.
        /// </returns>
        public override QueryScalarValue Evaluate(QueryBinaryOperation operation, QueryScalarValue firstValue, QueryScalarValue secondValue)
        {
            if (operation == QueryBinaryOperation.LessThan || operation == QueryBinaryOperation.LessThanOrEqualTo)
            {
                return(this.PerformNullSafeLessThan(firstValue, secondValue, operation));
            }

            return(base.Evaluate(operation, firstValue, secondValue));
        }
        /// <summary>
        /// Determines whether a typed data can do certain operation with another typed data
        /// </summary>
        /// <param name="operation">the operation</param>
        /// <param name="sourceType">the type of data to operation on</param>
        /// <param name="otherType">the other type</param>
        /// <returns>Value <c>true</c> if operation can be performed; otherwise, <c>false</c>.</returns>
        public override bool Supports(QueryBinaryOperation operation, QueryScalarType sourceType, QueryScalarType otherType)
        {
            if (this.IsSpatialType((IQueryClrType)sourceType) || this.IsSpatialType((IQueryClrType)otherType))
            {
                return false;
            }

            return base.Supports(operation, sourceType, otherType);
        }
        /// <summary>
        /// Performs a null safe less-than or less-than-or-equal comparison
        /// </summary>
        /// <param name="firstValue">The first value.</param>
        /// <param name="secondValue">The second value.</param>
        /// <param name="queryBinaryOperation">The query binary operation. Must be LessThan or LessThanOrEqualTo.</param>
        /// <returns>The result of the comparison.</returns>
        internal QueryScalarValue PerformNullSafeLessThan(QueryScalarValue firstValue, QueryScalarValue secondValue, QueryBinaryOperation queryBinaryOperation)
        {
            ExceptionUtilities.Assert(queryBinaryOperation == QueryBinaryOperation.LessThan || queryBinaryOperation == QueryBinaryOperation.LessThanOrEqualTo, "Unsupported  binary operation type {0}", queryBinaryOperation.ToString());

            // LinqToObjects will lazy treat any LessThan or LessThanOrEqual expression
            // where the first value is null as false UNLESS there is a specific comparison
            // method supplied. It so happens that for certain types the Astoria server
            // does supply the method, so the behavior is different based on the type
            bool result;
            if (ExpectLazyNullEvaluatiorForLessThan(firstValue))
            {
                result = false;
            }
            else
            {
                var comparisonResult = this.Compare(firstValue, secondValue);
                if (queryBinaryOperation == QueryBinaryOperation.LessThan)
                {
                    result = comparisonResult < 0;
                }
                else
                {
                    result = comparisonResult <= 0;
                }
            }

            return this.BooleanType.CreateValue(result);
        }
Example #7
0
        /// <summary>
        /// Performs a null safe less-than or less-than-or-equal comparison
        /// </summary>
        /// <param name="firstValue">The first value.</param>
        /// <param name="secondValue">The second value.</param>
        /// <param name="queryBinaryOperation">The query binary operation. Must be LessThan or LessThanOrEqualTo.</param>
        /// <returns>The result of the comparison.</returns>
        internal QueryScalarValue PerformNullSafeLessThan(QueryScalarValue firstValue, QueryScalarValue secondValue, QueryBinaryOperation queryBinaryOperation)
        {
            ExceptionUtilities.Assert(queryBinaryOperation == QueryBinaryOperation.LessThan || queryBinaryOperation == QueryBinaryOperation.LessThanOrEqualTo, "Unsupported  binary operation type {0}", queryBinaryOperation.ToString());

            // LinqToObjects will lazy treat any LessThan or LessThanOrEqual expression
            // where the first value is null as false UNLESS there is a specific comparison
            // method supplied. It so happens that for certain types the Astoria server
            // does supply the method, so the behavior is different based on the type
            bool result;

            if (ExpectLazyNullEvaluatiorForLessThan(firstValue))
            {
                result = false;
            }
            else
            {
                var comparisonResult = this.Compare(firstValue, secondValue);
                if (queryBinaryOperation == QueryBinaryOperation.LessThan)
                {
                    result = comparisonResult < 0;
                }
                else
                {
                    result = comparisonResult <= 0;
                }
            }

            return(this.BooleanType.CreateValue(result));
        }
 /// <summary>
 /// Determines whether an operation between two types is supported
 /// </summary>
 /// <param name="operation">the operation</param>
 /// <param name="sourceType">the type of data to operation on</param>
 /// <param name="otherType">the other type</param>
 /// <returns>Value <c>true</c> if operation can be performed; otherwise, <c>false</c>.</returns>
 public bool Supports(QueryBinaryOperation operation, QueryScalarType sourceType, QueryScalarType otherType)
 {
     throw new TaupoNotSupportedException("Attempt to use evaluation strategy from " + typeof(QueryUnresolvedType).Name + ". Please resolve expression first.");
 }
Example #9
0
 /// <summary>
 /// Determines whether an operation is applicable for this type
 /// </summary>
 /// <param name="operation">the operation</param>
 /// <returns>Value <c>true</c> if operation can be performed; otherwise, <c>false</c>.</returns>
 public bool Supports(QueryBinaryOperation operation)
 {
     return this.EvaluationStrategy.Supports(operation, this, this);
 }
Example #10
0
        /// <summary>
        /// Get properties in the structural type that support a specific Binary Operation.
        /// </summary>
        /// <param name="type">Structural Type.</param>
        /// <param name="op">An enum that represents a Query Binary Operation.</param>
        /// <returns>A collection of properties.</returns>
        protected IEnumerable <QueryProperty <QueryScalarType> > GetPropertiesWithBinaryOpSupport(QueryStructuralType type, QueryBinaryOperation op)
        {
            List <QueryProperty <QueryScalarType> > queryProperties = type.Properties.Primitive().Where(m => m.PropertyType.Supports(op)).ToList();

            DataServiceExecuteVerifier verifier = this.Verifier as DataServiceExecuteVerifier;

            if (verifier != null && verifier.IsUri == false)
            {
                if (op == QueryBinaryOperation.GreaterThan || op == QueryBinaryOperation.GreaterThanOrEqualTo || op == QueryBinaryOperation.LessThan || op == QueryBinaryOperation.LessThanOrEqualTo)
                {
                    // Exclude string, DateTime and boolean properties as these don't support greater than or less than operators in the Client Linq Code
                    queryProperties = queryProperties.Where(qp => (qp.PropertyType as IQueryClrType).ClrType != typeof(string)).ToList();
                    queryProperties = queryProperties.Where(qp => (qp.PropertyType as IQueryClrType).ClrType != typeof(bool)).ToList();
                    queryProperties = queryProperties.Where(qp => (qp.PropertyType as IQueryClrType).ClrType != typeof(DateTime)).ToList();
                    queryProperties = queryProperties.Where(qp => (qp.PropertyType as IQueryClrType).ClrType != typeof(Guid)).ToList();
                }
            }

            return(queryProperties);
        }
Example #11
0
        /// <summary>
        /// Determines whether data of this type can do certain operation with data of another type
        /// </summary>
        /// <param name="operation">the operation</param>
        /// <param name="otherScalarType">the other data type</param>
        /// <returns>Value <c>true</c> if operation can be performed; otherwise, <c>false</c>.</returns>
        public bool Supports(QueryBinaryOperation operation, QueryScalarType otherScalarType)
        {
            ExceptionUtilities.CheckArgumentNotNull(otherScalarType, "otherScalarType");

            return this.EvaluationStrategy.Supports(operation, this, otherScalarType);
        }
Example #12
0
        private QueryScalarValue EvaluateBinaryOperation(QueryScalarValue otherValue, QueryBinaryOperation operation)
        {
            ExceptionUtilities.CheckArgumentNotNull(otherValue, "otherValue");

            var result = this.EvaluationStrategy.Evaluate(operation, this, otherValue);

            var error = QueryError.Combine(this.EvaluationError, otherValue.EvaluationError);

            if (error != null)
            {
                result.EvaluationError = error;
            }

            return(result);
        }
 /// <summary>
 /// Do the specified BinaryOperation for the two values and returns the result.
 /// </summary>
 /// <param name="operation">The binary operation to perform.</param>
 /// <param name="firstValue">The first value.</param>
 /// <param name="secondValue">The second value.</param>
 /// <returns>Result of the operation.</returns>
 public QueryScalarValue Evaluate(QueryBinaryOperation operation, QueryScalarValue firstValue, QueryScalarValue secondValue)
 {
     throw new TaupoNotSupportedException("Attempt to use evaluation strategy from " + typeof(QueryUnresolvedType).Name + ". Please resolve expression first.");
 }
Example #14
0
        /// <summary>
        /// Determines whether data of this type can do certain operation with data of another type
        /// </summary>
        /// <param name="operation">the operation</param>
        /// <param name="otherScalarType">the other data type</param>
        /// <returns>Value <c>true</c> if operation can be performed; otherwise, <c>false</c>.</returns>
        public bool Supports(QueryBinaryOperation operation, QueryScalarType otherScalarType)
        {
            ExceptionUtilities.CheckArgumentNotNull(otherScalarType, "otherScalarType");

            return(this.EvaluationStrategy.Supports(operation, this, otherScalarType));
        }
        /// <summary>
        /// Do the specified BinaryOperation for the two values and returns the result.
        /// </summary>
        /// <param name="operation">The binary operation to perform.</param>
        /// <param name="firstValue">The first value.</param>
        /// <param name="secondValue">The second value.</param>
        /// <returns>Result of the operation.</returns>
        public virtual QueryScalarValue Evaluate(QueryBinaryOperation operation, QueryScalarValue firstValue, QueryScalarValue secondValue)
        {
            Func <object, object, Type, object> evaluationMethod = null;

            switch (operation)
            {
            case QueryBinaryOperation.Add:
                evaluationMethod = ArithmeticEvaluationHelper.Add;
                break;

            case QueryBinaryOperation.Subtract:
                evaluationMethod = ArithmeticEvaluationHelper.Subtract;
                break;

            case QueryBinaryOperation.Multiply:
                evaluationMethod = ArithmeticEvaluationHelper.Multiply;
                break;

            case QueryBinaryOperation.Divide:
                evaluationMethod = ArithmeticEvaluationHelper.Divide;
                break;

            case QueryBinaryOperation.Modulo:
                evaluationMethod = ArithmeticEvaluationHelper.Modulo;
                break;

            case QueryBinaryOperation.BitwiseAnd:
                evaluationMethod = ArithmeticEvaluationHelper.BitwiseAnd;
                break;

            case QueryBinaryOperation.BitwiseOr:
                evaluationMethod = ArithmeticEvaluationHelper.BitwiseOr;
                break;

            case QueryBinaryOperation.BitwiseExclusiveOr:
                evaluationMethod = ArithmeticEvaluationHelper.ExclusiveOr;
                break;

            case QueryBinaryOperation.LogicalAnd:
                return(this.BooleanType.CreateValue((bool)firstValue.Value && (bool)secondValue.Value));

            case QueryBinaryOperation.LogicalOr:
                return(this.BooleanType.CreateValue((bool)firstValue.Value || (bool)secondValue.Value));

            case QueryBinaryOperation.EqualTo:
                return(this.BooleanType.CreateValue(this.AreEqual(firstValue, secondValue)));

            case QueryBinaryOperation.NotEqualTo:
                return(this.BooleanType.CreateValue(!this.AreEqual(firstValue, secondValue)));

            case QueryBinaryOperation.LessThan:
                return(this.BooleanType.CreateValue(this.Compare(firstValue, secondValue) < 0));

            case QueryBinaryOperation.LessThanOrEqualTo:
                return(this.BooleanType.CreateValue(this.Compare(firstValue, secondValue) <= 0));

            case QueryBinaryOperation.GreaterThan:
                return(this.BooleanType.CreateValue(this.Compare(firstValue, secondValue) > 0));

            case QueryBinaryOperation.GreaterThanOrEqualTo:
                return(this.BooleanType.CreateValue(this.Compare(firstValue, secondValue) >= 0));

            case QueryBinaryOperation.Concat:
                return(new QueryClrPrimitiveType(typeof(string), this).CreateValue(firstValue.Value.ToString() + secondValue.Value.ToString()));

            default:
                throw new TaupoNotSupportedException("Unsupported query binary operation.");
            }

            ExceptionUtilities.Assert(evaluationMethod != null, "evaluationMethod should not be null.");
            return(this.ExecuteBinaryOperation(firstValue, secondValue, evaluationMethod));
        }
Example #16
0
 /// <summary>
 /// Determines whether an operation is applicable for this type
 /// </summary>
 /// <param name="operation">the operation</param>
 /// <returns>Value <c>true</c> if operation can be performed; otherwise, <c>false</c>.</returns>
 public bool Supports(QueryBinaryOperation operation)
 {
     return(this.EvaluationStrategy.Supports(operation, this, this));
 }
Example #17
0
        /// <summary>
        /// Get properties in the structural type that support a specific Binary Operation.
        /// </summary>
        /// <param name="type">Structural Type.</param>
        /// <param name="op">An enum that represents a Query Binary Operation.</param>
        /// <returns>A collection of properties.</returns>
        protected IEnumerable<QueryProperty<QueryScalarType>> GetPropertiesWithBinaryOpSupport(QueryStructuralType type, QueryBinaryOperation op)
        {
            List<QueryProperty<QueryScalarType>> queryProperties = type.Properties.Primitive().Where(m => m.PropertyType.Supports(op)).ToList();

            DataServiceExecuteVerifier verifier = this.Verifier as DataServiceExecuteVerifier;
            if (verifier != null && verifier.IsUri == false)
            {
                if (op == QueryBinaryOperation.GreaterThan || op == QueryBinaryOperation.GreaterThanOrEqualTo || op == QueryBinaryOperation.LessThan || op == QueryBinaryOperation.LessThanOrEqualTo)
                {
                    // Exclude string, DateTime and boolean properties as these don't support greater than or less than operators in the Client Linq Code
                    queryProperties = queryProperties.Where(qp => (qp.PropertyType as IQueryClrType).ClrType != typeof(string)).ToList();
                    queryProperties = queryProperties.Where(qp => (qp.PropertyType as IQueryClrType).ClrType != typeof(bool)).ToList();
                    queryProperties = queryProperties.Where(qp => (qp.PropertyType as IQueryClrType).ClrType != typeof(DateTime)).ToList();
#if !WINDOWS_PHONE
                    queryProperties = queryProperties.Where(qp => (qp.PropertyType as IQueryClrType).ClrType != typeof(Guid)).ToList();
#endif
                }
            }

            return queryProperties;
        }