/// <summary> /// Do the specified UnaryOperation for the value and returns the result. /// </summary> /// <param name="operation">The binary operation to perform.</param> /// <param name="value">The value.</param> /// <returns>Result of the operation.</returns> public virtual QueryScalarValue Evaluate(QueryUnaryOperation operation, QueryScalarValue value) { Func <object, Type, object> evaluationMethod = null; switch (operation) { case QueryUnaryOperation.LogicalNegate: return(this.BooleanType.CreateValue(!(bool)value.Value)); case QueryUnaryOperation.Negate: evaluationMethod = ArithmeticEvaluationHelper.Negate; break; case QueryUnaryOperation.BitwiseNot: evaluationMethod = ArithmeticEvaluationHelper.BitwiseNot; break; default: throw new TaupoNotSupportedException("Unsupported query unary operation."); } ExceptionUtilities.Assert(evaluationMethod != null, "evaluationMethod should not be null."); Type clrType = ((QueryClrPrimitiveType)value.Type).ClrType; object result = evaluationMethod(value.Value, clrType); return(value.Type.CreateValue(result)); }
private QueryScalarValue ExecuteBinaryOperation(QueryScalarValue firstValue, QueryScalarValue secondValue, Func <object, object, Type, object> evaluationMethod) { var t1 = (QueryClrPrimitiveType)firstValue.Type; var t2 = (QueryClrPrimitiveType)secondValue.Type; object v1 = firstValue.Value; object v2 = secondValue.Value; QueryClrPrimitiveType commonType = t1; try { commonType = (QueryClrPrimitiveType)this.GetCommonType(t1, t2); if (v1 == null || v2 == null) { return(commonType.CreateErrorValue(new QueryError("Null values are not supported for the operation."))); } var result = evaluationMethod(v1, v2, commonType.ClrType); return(commonType.CreateValue(result)); } catch (Exception ex) { return(commonType.CreateErrorValue(new QueryError(ex.Message))); } }
private QueryValue VisitFirstExpression(LinqQueryMethodWithLambdaExpression expression, bool isOrDefault) { var source = this.EvaluateCollection(expression.Source); IEnumerable <QueryValue> elements = source.Elements; if (expression.Lambda != null) { // Note: cannot directly use souce.Where(...) since underlying store semantics might change order! elements = source.Elements.Where(v => { QueryScalarValue predicate = this.EvaluateLambda <QueryScalarValue>(expression.Lambda, v); return(!predicate.IsNull && (bool)predicate.Value); }).ToArray(); } if (elements.Count() == 0) { if (isOrDefault) { return(source.Type.ElementType.NullValue); } else { var expectedException = new ExpectedExceptions(new ExpectedExceptionTypeMessageVerifier <InvalidOperationException>(null, "Sequence contains no elements")); return(source.Type.ElementType.CreateErrorValue(expectedException)); } } else { return(elements.First()); } }
/// <summary> /// Visits a LinqAddQueryOptionExpression. /// </summary> /// <param name="expression">The expression.</param> /// <returns>Value of the expression</returns> public QueryValue Visit(LinqToAstoriaAddQueryOptionExpression expression) { ExceptionUtilities.CheckArgumentNotNull(expression, "expression"); string queryOption = expression.QueryOption; if (queryOption.Equals("$top", StringComparison.OrdinalIgnoreCase) || queryOption.Equals("$skip", StringComparison.OrdinalIgnoreCase)) { var source = this.EvaluateCollection(expression.Source); var evalStrategy = new LinqToAstoriaClrQueryEvaluationStrategy(); QueryScalarValue count = new QueryScalarValue(evalStrategy.IntegerType, (int)expression.QueryValue, null, evalStrategy); if (queryOption.Equals("$top", StringComparison.OrdinalIgnoreCase)) { return(source.Take(count)); } else { return(source.Skip(count)); } } else { return(this.Evaluate(expression.Source)); } }
/// <summary> /// Returns whether or not to expect lazy evaluation of less than for a null first value. /// </summary> /// <param name="firstValue">The first value.</param> /// <returns>True if lazy null evaluation should be expected</returns> internal static bool ExpectLazyNullEvaluatiorForLessThan(QueryScalarValue firstValue) { var clrType = ((IQueryClrType)firstValue.Type).ClrType; bool lazyNullEvaluation = firstValue.IsNull && IsSpecialCaseTypeForLessThan(clrType) && !firstValue.IsDynamicPropertyValue(); return(lazyNullEvaluation); }
/// <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> /// Gets the expected query value for the action request /// </summary> /// <param name="initialExpectedResults">Initial expected values for an action</param> /// <param name="parameterValues">Parameter values for the action</param> /// <returns>A query Value that is the expected value</returns> public QueryValue GetExpectedQueryValue(QueryValue initialExpectedResults, params QueryValue[] parameterValues) { ExceptionUtilities.CheckArgumentNotNull(initialExpectedResults, "initialExpectedResults"); QueryStructuralValue initialStructuralValue = initialExpectedResults as QueryStructuralValue; ExceptionUtilities.CheckArgumentNotNull(initialStructuralValue, "initialStructuralValue"); QueryScalarValue initialScalarValue = initialStructuralValue.GetScalarValue(this.IntegerProperty); ExceptionUtilities.CheckArgumentNotNull(initialScalarValue, "initialScalarValue"); int intPropertyValue = (int)initialScalarValue.Value; ExceptionUtilities.CheckArgumentNotNull(intPropertyValue, "intPropertyValue"); if (intPropertyValue != int.MaxValue) { initialStructuralValue.SetPrimitiveValue(this.IntegerProperty, intPropertyValue + 1); } else { initialStructuralValue.SetPrimitiveValue(this.IntegerProperty, 0); } return(initialStructuralValue); }
/// <summary> /// Creates a copy of the given value recursively /// </summary> /// <param name="value">The value to copy</param> /// <returns>The copied value</returns> public virtual QueryValue Visit(QueryScalarValue value) { return(this.HandleCommonCasesAndCache( value, () => value.Type.CreateValue(value.Value), null)); }
/// <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> /// 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> /// Visits a QueryScalarValue and returns the clr value of the primitive value /// </summary> /// <param name="value">The QueryScalarValue which contains the clr value of the primitive value</param> /// <returns>the clr value of the primitive value</returns> public object Visit(QueryScalarValue value) { if (value.IsNull || value.Value == UninitializedData.Value) { return(null); } return(value.Value); }
/// <summary> /// Compares the given clr value value to the given query scalar value, and throws a DataComparisonException if they dont match /// </summary> /// <param name="expected">expected CLR value</param> /// <param name="actual">actual query primitive value to compare</param> /// <param name="assert">The assertion handler to use</param> public void Compare(object expected, QueryScalarValue actual, AssertionHandler assert) { if (actual.IsDynamicPropertyValue()) { expected = this.converter.SerializePrimitive(expected); actual = new QueryClrPrimitiveType(typeof(string), actual.Type.EvaluationStrategy).CreateValue(this.converter.SerializePrimitive(actual.Value)); } this.UnderlyingComparer.Compare(expected, actual, assert); }
/// <summary> /// Compares the given clr value to the given query scalar value, and throws a DataComparisonException if they dont match /// </summary> /// <param name="expected">expected CLR value</param> /// <param name="actual">actual query primitive value to compare</param> /// <param name="assert">The assertion handler to use</param> public override void Compare(object expected, QueryScalarValue actual, AssertionHandler assert) { ExceptionUtilities.CheckArgumentNotNull(actual, "actual"); if (actual.IsDynamicPropertyValue() && !(actual.Type is QueryClrSpatialType)) { this.CompareDynamicValues(actual.Type, expected, actual.Value, assert); } else { base.Compare(expected, actual, assert); } }
/// <summary> /// Casts a <see cref="QueryScalarValue"/> to a <see cref="QueryScalarType"/>. The cast will return the value type cast to the new type. /// </summary> /// <param name="source">The source for the cast operation.</param> /// <param name="type">The type for the cast operation.</param> /// <returns><see cref="QueryScalarValue"/> which is cast to the appropriate type</returns> public QueryScalarValue Cast(QueryScalarValue source, QueryScalarType type) { var targetType = (QueryClrPrimitiveType)type; try { return(this.EvaluateCast(source.Value, targetType)); } catch (InvalidCastException) { return(targetType.CreateValue(null)); } }
/// <summary> /// Compares primitive object with the expected value. /// </summary> /// <param name="expected">Expected value.</param> /// <param name="actual">Actual value.</param> /// <param name="path">The path to the compared object (for debugging purposes).</param> /// <param name="shouldThrow">Should exception be thrown if error is encountered.</param> /// <returns>Result of the comparison, Success or Failure.</returns> protected ComparisonResult ComparePrimitive(QueryScalarValue expected, object actual, string path, bool shouldThrow) { this.AddToLogBuffer("Verifying scalar value. Path: {0}", path); if (actual == null) { if (expected.Value == null) { return(ComparisonResult.Success); } this.ThrowOrLogError(shouldThrow, "Expecting non-null value: {0} in '{1}'. Got null value instead.", expected, path); return(ComparisonResult.Failure); } if (expected.Value == null) { this.ThrowOrLogError(shouldThrow, "Expecting null value in '{0}'. Actual: {1}[{2}].", path, actual, actual.GetType()); return(ComparisonResult.Failure); } if (expected.Value.GetType().IsEnum() || actual.GetType().IsEnum()) { if (expected.Value.GetType().IsEnum() && actual.GetType().IsEnum()) { return(expected.Value.Equals(actual) ? ComparisonResult.Success : ComparisonResult.Failure); } else { // If only one value is a clr enum then it is a failure because it either means there is an error in the evaluator or // the result materialization in the product. (Valid enum values should always be materialized as enum objects rather than // integer values) return(ComparisonResult.Failure); } } if (expected.Type.EvaluationStrategy.AreEqual(expected, expected.Type.CreateValue(actual))) { this.AddToLogBuffer("Verifying scalar value. Path: {0} SUCCESSFUL", path); return(ComparisonResult.Success); } else { this.ThrowOrLogError(shouldThrow, "Scalar value mismatch in '{0}'. Expected: {1}. Actual: {2}[{3}].", path, expected, actual, actual.GetType()); return(ComparisonResult.Failure); } }
private bool WriteErrorIfNotEqual(string propertyPath, object expected, QueryScalarValue value) { try { this.comparer.Compare(expected, value, this.Assert); } catch (TestFailedException e) { this.errors.Add(string.Format(CultureInfo.InvariantCulture, "Error: value at property '{0}' did not match. {1}", propertyPath, e.Message)); return(false); } return(true); }
/// <summary> /// Evaluates the specified expression. /// </summary> /// <param name="expression">The expression to evaluate.</param> /// <returns>Value of the expression.</returns> public virtual QueryValue Visit(LinqNewInstanceExpression expression) { if (expression.ExpressionType is QueryStructuralType) { QueryStructuralType queryType = (QueryStructuralType)expression.ExpressionType; QueryStructuralValue instance = queryType.CreateNewInstance(); foreach (var property in queryType.Properties.Where(p => !(p.PropertyType is QueryScalarType))) { instance.SetValue(property.Name, property.PropertyType.DefaultValue); } for (int i = 0; i < expression.Members.Count; ++i) { instance.SetValue(expression.MemberNames[i], this.Evaluate(expression.Members[i])); } return(instance); } else if (expression.ExpressionType is QueryCollectionType) { // for QueryCollectionTypes we only support constructor arguments, hence we will only be evaluating constructor arguments. QueryCollectionValue instance = ((QueryCollectionType)expression.ExpressionType).CreateCollectionWithValues(expression.ConstructorArguments.Select(arg => this.Evaluate(arg))); return(instance); } else { var scalarType = expression.ExpressionType as QueryScalarType; ExceptionUtilities.CheckObjectNotNull(scalarType, "QueryType is not a supported type"); ExceptionUtilities.Assert(expression.ConstructorArguments.Count == 1, "Cannot pass multiple arguments to PrimitiveType constructor"); var constructorArgument = expression.ConstructorArguments.Select(this.Evaluate).Single(); QueryScalarValue instance = scalarType.CreateValue(constructorArgument); return(instance); } }
/// <summary> /// Compares primitive object with the expected value. /// </summary> /// <param name="expected">Expected value.</param> /// <param name="actual">Actual value.</param> /// <param name="path">The path to the compared object (for debugging purposes).</param> /// <param name="shouldThrow">Should exception be thrown if error is encountered.</param> /// <returns>Result of the comparison, Success, Failure or Skipped.</returns> protected ComparisonResult ComparePrimitive(QueryScalarValue expected, object actual, string path, bool shouldThrow) { this.AddToLogBuffer("Verifying scalar value. Path: {0}", path); if (actual == null) { if (expected.Value == null) { return(ComparisonResult.Success); } this.ThrowOrLogError(shouldThrow, "Expecting non-null value: {0} in '{1}'. Got null value instead.", expected, path); return(ComparisonResult.Failure); } if (expected.Value == null) { this.ThrowOrLogError(shouldThrow, "Expecting null value in '{0}'. Actual: {1}[{2}].", path, actual, actual.GetType()); return(ComparisonResult.Failure); } if (expected.Type.EvaluationStrategy.AreEqual(expected, expected.Type.CreateValue(actual))) { this.AddToLogBuffer("Verifying scalar value. Path: {0} SUCCESSFUL", path); return(ComparisonResult.Success); } else { this.ThrowOrLogError(shouldThrow, "Scalar value mismatch in '{0}'. Expected: {1}. Actual: {2}[{3}].", path, expected, actual, actual.GetType()); return(ComparisonResult.Failure); } }
/// <summary> /// Returns whether or not to expect lazy evaluation of less than for a null first value. /// </summary> /// <param name="firstValue">The first value.</param> /// <returns>True if lazy null evaluation should be expected</returns> internal static bool ExpectLazyNullEvaluatiorForLessThan(QueryScalarValue firstValue) { var clrType = ((IQueryClrType)firstValue.Type).ClrType; bool lazyNullEvaluation = firstValue.IsNull && IsSpecialCaseTypeForLessThan(clrType) && !firstValue.IsDynamicPropertyValue(); return lazyNullEvaluation; }
/// <summary> /// Evaluates the property. /// </summary> /// <param name="resultType">Type of the result.</param> /// <param name="propertyName">Name of the property.</param> /// <param name="instance">The instance.</param> /// <returns> /// Query value which is the result of the function evaluation. /// </returns> private QueryValue EvaluateProperty(QueryScalarType resultType, string propertyName, QueryScalarValue instance) { if (instance.Value == null) { // TODO: evaluation error? return(resultType.NullValue); } var type = instance.Value.GetType(); var propertyInfo = type.GetProperty(propertyName); ExceptionUtilities.CheckObjectNotNull(propertyInfo, "Could not find property named '{0}' on '{1}'", propertyName, instance.Value); var value = propertyInfo.GetValue(instance.Value, null); return(resultType.CreateValue(value)); }
/// <summary> /// Factory method to create the <see cref="QueryConstantExpression"/>. /// </summary> /// <param name="scalarValue">Scalar value.</param> /// <returns>The <see cref="QueryConstantExpression"/> with the provided arguments.</returns> public static QueryConstantExpression Constant(QueryScalarValue scalarValue) { ExceptionUtilities.CheckArgumentNotNull(scalarValue, "scalarValue"); return new QueryConstantExpression(scalarValue); }
/// <summary> /// Visits the given QueryValue /// </summary> /// <param name="value">QueryValue being visited.</param> /// <returns>The result of visiting this QueryValue.</returns> public QueryValue Visit(QueryScalarValue value) { return(value); }
/// <summary> /// Compares the given query scalar value to the given clr value, and throws a DataComparisonException if they dont match /// </summary> /// <param name="expected">expected query primitive value to compare</param> /// <param name="actual">actual CLR value</param> /// <param name="assert">The assertion handler to use</param> public virtual void Compare(QueryScalarValue expected, object actual, AssertionHandler assert) { ExceptionUtilities.CheckArgumentNotNull(expected, "expected"); ExceptionUtilities.CheckArgumentNotNull(assert, "assert"); this.Compare(expected.Type, expected.Value, actual, assert); }
private bool WriteErrorIfNotEqual(string propertyPath, object expected, QueryScalarValue value) { try { this.comparer.Compare(expected, value, this.Assert); } catch (TestFailedException e) { this.errors.Add(string.Format(CultureInfo.InvariantCulture, "Error: value at property '{0}' did not match. {1}", propertyPath, e.Message)); return false; } return true; }
/// <summary> /// Compares the given clr value to the given query scalar value, and throws a DataComparisonException if they dont match /// </summary> /// <param name="expected">expected CLR value</param> /// <param name="actual">actual query primitive value to compare</param> /// <param name="assert">The assertion handler to use</param> public virtual void Compare(object expected, QueryScalarValue actual, AssertionHandler assert) { ExceptionUtilities.CheckArgumentNotNull(actual, "actual"); ExceptionUtilities.CheckArgumentNotNull(assert, "assert"); this.Compare(actual.Type, expected, actual.Value, assert); }
/// <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)); }
internal QueryConstantExpression(QueryScalarValue primitiveValue) : base(primitiveValue.Type) { this.ScalarValue = primitiveValue; }
/// <summary> /// Factory method to create the <see cref="QueryConstantExpression"/>. /// </summary> /// <param name="scalarValue">Scalar value.</param> /// <returns>The <see cref="QueryConstantExpression"/> with the provided arguments.</returns> public static QueryConstantExpression Constant(QueryScalarValue scalarValue) { ExceptionUtilities.CheckArgumentNotNull(scalarValue, "scalarValue"); return(new QueryConstantExpression(scalarValue)); }
/// <summary> /// Compares the primitive value to another value and returns their relative ordering. /// </summary> /// <param name="value">First value.</param> /// <param name="otherValue">Second value.</param> /// <returns> /// Integer which is less than zero if this value is less than the other value, 0 if they are equal, /// greater than zero if this value is greater than the other value /// </returns> public int Compare(QueryScalarValue value, QueryScalarValue otherValue) { var t1 = (QueryClrPrimitiveType)value.Type; var t2 = (QueryClrPrimitiveType)otherValue.Type; object v1 = value.Value; object v2 = otherValue.Value; if (this.IsSpatialType(t1)) { ExceptionUtilities.Assert(this.IsSpatialType(t2), "Because CLR types match, both values should both be spatial. Type was '{0}'", t2); ExceptionUtilities.CheckObjectNotNull(this.SpatialEqualityComparer, "Cannot compare spatial values without a spatial equality-comparer"); return(this.SpatialEqualityComparer.Equals(v1, v2) ? 0 : 2); } if (t1.ClrType != t2.ClrType) { Type commonClrType = LinqTypeSemantics.GetCommonType(t1.ClrType, t2.ClrType); commonClrType = Nullable.GetUnderlyingType(commonClrType) ?? commonClrType; if (v1 != null) { v1 = ArithmeticEvaluationHelper.ChangeType(v1, commonClrType); } if (v2 != null) { v2 = ArithmeticEvaluationHelper.ChangeType(v2, commonClrType); } } if (v1 == null) { if (v2 == null) { // both null - are equal return(0); } else { // first null, second not-null return(-1); } } else { if (v2 == null) { // first not null, second null return(1); } } var bytes1 = v1 as byte[]; if (bytes1 != null) { var bytes2 = (byte[])v2; return(CompareByteArrays(bytes1, bytes2)); } IComparable cv1 = (IComparable)v1; return(cv1.CompareTo(v2)); }
/// <summary> /// Compares the primitive value to another value and returns their relative ordering. /// </summary> /// <param name="value">First value.</param> /// <param name="otherValue">Second value.</param> /// <returns> /// True if the values are equal. /// </returns> public bool AreEqual(QueryScalarValue value, QueryScalarValue otherValue) { return(this.Compare(value, otherValue) == 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> /// Visits the QueryScalarValue /// </summary> /// <param name="value">Value to visit</param> /// <returns>will always throw</returns> public string Visit(QueryScalarValue value) { this.builder.AppendLine(string.Format(CultureInfo.InvariantCulture, value.IsNull ? "<null>" : value.Value.ToString())); return(null); }
/// <summary> /// Visits a payload element whose root is a PrimitiveValue. /// </summary> /// <param name="payloadElement">The root node of payload element being visited.</param> public void Visit(PrimitiveValue payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); var current = this.expectedValueStack.Peek(); var value = current as QueryScalarValue; if (value == null) { // handle named stream value var streamValue = current as AstoriaQueryStreamValue; ExceptionUtilities.CheckObjectNotNull(streamValue, "Value was not a primitive value or a stream. Value was: '{0}'", current.ToString()); // TODO: verify the binary content of the stream is correct } else { this.VerifyTypeName(value, payloadElement.FullTypeName, "Type name did not match expectation for primitive value"); if (value.IsNull) { this.parent.Assert.IsTrue(payloadElement.IsNull, "Primitive value unexpectedly non-null"); } else { this.parent.Assert.IsFalse(payloadElement.IsNull, "Primitive value unexpectedly null"); if (value.Value is DateTime && ((DateTime)value.Value).Kind == DateTimeKind.Local && this.parent.ExpectedPayloadOptions.HasFlag(ODataPayloadOptions.UseOldDateTimeFormat)) { // The old DateTime format cannot represent Local DateTimes, so convert the expected value to Utc value = new QueryScalarValue(value.Type, TimeZoneInfo.ConvertTime((DateTime)value.Value, TimeZoneInfo.Utc), value.EvaluationError, this.parent.QueryEvaluationStrategy); } ExceptionUtilities.CheckObjectNotNull(this.parent.PrimitiveValueComparer, "Cannot compare primitive values without primitive comparer"); this.parent.PrimitiveValueComparer.Compare(value, payloadElement.ClrValue, this.parent.Assert); } } }
/// <summary> /// Evaluates the property. /// </summary> /// <param name="resultType">Type of the result.</param> /// <param name="propertyName">Name of the property.</param> /// <param name="instance">The instance.</param> /// <returns> /// Query value which is the result of the function evaluation. /// </returns> private QueryValue EvaluateProperty(QueryScalarType resultType, string propertyName, QueryScalarValue instance) { if (instance.Value == null) { // TODO: evaluation error? return resultType.NullValue; } var type = instance.Value.GetType(); var propertyInfo = type.GetProperty(propertyName); ExceptionUtilities.CheckObjectNotNull(propertyInfo, "Could not find property named '{0}' on '{1}'", propertyName, instance.Value); var value = propertyInfo.GetValue(instance.Value, null); return resultType.CreateValue(value); }
/// <summary> /// Evaluates the specified expression. /// </summary> /// <param name="expression">The expression to evaluate.</param> /// <returns>Value of the expression.</returns> public virtual QueryValue Visit(QueryCustomFunctionCallExpression expression) { QueryValue result; var argumentValues = this.EvaluateArguments(expression.Arguments); var customEvaluator = expression.Function.Annotations.OfType <FunctionEvaluatorAnnotation>().Select(a => a.FunctionEvaluator).SingleOrDefault(); if (customEvaluator != null) { result = customEvaluator(expression.ExpressionType, argumentValues); } else if (expression.FunctionBody != null) { QueryExpression functionBody = expression.FunctionBody; // replace parameter refs with arguments if (expression.Function.Parameters.Any()) { // Consider query: // "select value DefaultNamespace.GetCustomer(c.CustomerId) from [DefaultContainer].[Customer] as c" where GetCustomer is a function. // After we replace parameter references in the function's body with "c.CustomerId" expression evaluation // of the body expression fails becuase variable "c" is not in the scope for the function's body. // Note also that function body itself can have a variable reference with the same name "c". // So the right thing is to evaluate each argument and then replace parameter references with constant expressions. // However QueryConstantExpression currently only supports QueryScalarType/QueryScalarValue. // So for now we only evaluating scalar arguments. // TODO: add supoort for non-scalar constants and change the following code to evaluate each argument // NOTE: we have similar limitation in LinqToEntitiesEvaluator List <QueryExpression> evaluatedArguments = new List <QueryExpression>(); foreach (var argument in expression.Arguments) { QueryScalarType scalarArgumentType = argument.ExpressionType as QueryScalarType; if (scalarArgumentType != null) { QueryScalarValue scalarValue = (QueryScalarValue)this.Evaluate(argument); var constant = CommonQueryBuilder.Constant(scalarValue); evaluatedArguments.Add(constant); } else { evaluatedArguments.Add(argument); } } var visitor = this.CreateFunctionParameterReferenceReplacingVisitor(expression.Function, evaluatedArguments); functionBody = visitor.ReplaceExpression(expression.FunctionBody); } result = this.Evaluate(functionBody); } else { result = expression.ExpressionType.EvaluationStrategy.EvaluateFunction( expression.ExpressionType, expression.Function, argumentValues); } return(result); }