/// <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());
            }
        }
Beispiel #4
0
            /// <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));
                }
            }
Beispiel #5
0
        /// <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);
        }
Beispiel #6
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>
        /// 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));
 }
Beispiel #9
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>
 /// 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 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>
        /// 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);
            }
        }
Beispiel #17
0
        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>
            /// 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);
            }
Beispiel #24
0
 /// <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 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);
 }
 /// <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));
        }
Beispiel #30
0
 internal QueryConstantExpression(QueryScalarValue primitiveValue)
     : base(primitiveValue.Type)
 {
     this.ScalarValue = primitiveValue;
 }
Beispiel #31
0
        /// <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);
        }
Beispiel #35
0
 /// <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>
 /// 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>
            /// 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);
        }
Beispiel #39
0
        /// <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);
        }