/// <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> /// 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."); } }
/// <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); }
/// <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."); }
/// <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); }
/// <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); }
/// <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); }
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."); }
/// <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)); }
/// <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)); }
/// <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; }