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

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

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

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

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

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

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

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

            default:
                throw new TaupoNotSupportedException("Unsupported query binary operation.");
            }
        }
        /// <summary>
        /// Determines whether a typed data can do certain operation
        /// </summary>
        /// <param name="operation">the operation</param>
        /// <param name="sourceType">the type of data to operate on</param>
        /// <returns>Value <c>true</c> if operation can be performed; otherwise, <c>false</c>.</returns>
        public bool Supports(QueryUnaryOperation operation, QueryScalarType sourceType)
        {
            switch (operation)
            {
            case QueryUnaryOperation.LogicalNegate:
                return(((IQueryClrType)sourceType).ClrType == typeof(bool));

            default:
                throw new TaupoNotSupportedException("Unsupported query unary operation.");
            }
        }
Пример #4
0
        /// <summary>
        /// Factory method to create the <see cref="QueryConstantExpression"/>.
        /// </summary>
        /// <param name="value">Value of the expression.</param>
        /// <param name="valueType">Type of the expression.</param>
        /// <returns>The <see cref="QueryConstantExpression"/> with the provided arguments.</returns>
        public static QueryConstantExpression Constant(object value, QueryScalarType valueType)
        {
            ExceptionUtilities.CheckArgumentNotNull(valueType, "valueType");

            if (value == null)
            {
                ExceptionUtilities.Assert(!valueType.IsUnresolved, "When value is null type cannot be unresolved.");
            }

            return(Constant(valueType.CreateValue(value)));
        }
        /// <summary>
        /// Determines whether a type supports ordering.
        /// </summary>
        /// <param name="sourceType">the type of data to operation on</param>
        /// <returns>Value <c>true</c> if ordering can be performed; otherwise, <c>false</c>.</returns>
        public bool SupportsOrderComparison(QueryScalarType sourceType)
        {
            // Ordering is supported for all primitive types in the clr
            // Note, this is ordering in the sense of "orderby p.ProductName", not Where(p => p.ProductName < "foo" ).
            var spatialType = sourceType as QueryClrSpatialType;

            if (spatialType != null)
            {
                return(false);
            }

            return(true);
        }
        /// <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>
        /// 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));
        }
Пример #8
0
        private void BuildStructuralPropertiesQueryValue(QueryStructuralValue instance, string propertyPath, IList <MemberProperty> properties, IList <QueryProperty> queryProperties, EntitySetDataRow row)
        {
            ExceptionUtilities.Assert(properties.Count == queryProperties.Count, "QueryProperties '{0}' and MemberProperties '{1}' are not the same number!", CreateQueryPropertyList(queryProperties), CreateMemberPropertyList(properties));

            // TODO: Some Taupo framework pieces skip over StreamDataType properties
            foreach (MemberProperty childProperty in properties.Where(p => !(p.PropertyType is StreamDataType)))
            {
                string childPropertyPath = propertyPath + childProperty.Name;
                List <QueryProperty> childQueryProperties = queryProperties.Where(p => p.Name == childProperty.Name).ToList();
                ExceptionUtilities.Assert(childQueryProperties.Count == 1, "Could not find query property based on MemberProperty Name '{0}' in list of query properties '{1}'", childProperty.Name, CreateQueryPropertyList(childQueryProperties));

                QueryProperty childQueryProperty = childQueryProperties.First();

                QueryCollectionType childCollectionDataType = childQueryProperty.PropertyType as QueryCollectionType;
                QueryScalarType     childScalarType         = childQueryProperty.PropertyType as QueryScalarType;
                QueryComplexType    childComplexType        = childQueryProperty.PropertyType as QueryComplexType;

                if (childCollectionDataType != null)
                {
                    instance.SetValue(childProperty.Name, this.BuildCollectionQueryValue(childPropertyPath + ".", childCollectionDataType, row));
                }
                else if (childScalarType != null)
                {
                    var value      = row[childPropertyPath];
                    var queryValue = childScalarType.CreateValue(value);
                    instance.SetValue(childQueryProperty.Name, queryValue);
                }
                else
                {
                    ExceptionUtilities.CheckObjectNotNull(childComplexType, "Unknown type '{0}'", childProperty.PropertyType);

                    // If a complex type instance is null in the datarow, we will create a QueryStructuralValue indicating null and set it on the instance.
                    if (row.PropertyPaths.Contains(childPropertyPath) && row[childPropertyPath] == null)
                    {
                        instance.SetValue(childProperty.Name, new QueryStructuralValue(childComplexType, true, null, childComplexType.EvaluationStrategy));
                    }
                    else
                    {
                        QueryStructuralValue childInstance = childComplexType.CreateNewInstance();
                        this.BuildStructuralPropertiesQueryValue(childInstance, childPropertyPath + ".", childComplexType.ComplexType.Properties, childComplexType.Properties, row);
                        instance.SetValue(childProperty.Name, childInstance);
                    }
                }
            }
        }
        /// <summary>
        /// Compares the given values of the given type, and throws a DataComparisonException or AssertionFailedException if values don't match
        /// </summary>
        /// <param name="type">The expected type</param>
        /// <param name="expected">The expected value</param>
        /// <param name="actual">The actual value</param>
        /// <param name="assert">The assertion handler to use</param>
        protected virtual void Compare(QueryScalarType type, object expected, object actual, AssertionHandler assert)
        {
            ExceptionUtilities.CheckArgumentNotNull(type, "type");
            ExceptionUtilities.CheckArgumentNotNull(assert, "assert");

            if (expected == type.NullValue.Value)
            {
                assert.IsNull(actual, "Primitive value unexpectedly non-null");
            }
            else
            {
                assert.IsNotNull(actual, "Primitive value unexpectedly null");

                assert.AreEqual(expected.GetType(), actual.GetType(), EqualityComparer <Type> .Default, "Types did not match");

                var comparer = new DelegateBasedEqualityComparer <QueryScalarValue>((v1, v2) => v1.Type.EvaluationStrategy.Compare(v1, v2) == 0);
                assert.AreEqual(type.CreateValue(expected), type.CreateValue(actual), comparer, "Primitive value did not match");
            }
        }
Пример #10
0
        /// <summary>
        /// Build the collection of primitive types which will be set on the constructed repository
        /// </summary>
        /// <param name="queryTypeLibrary">Query Type Library to build Types from</param>
        protected override void BuildPrimitiveTypes(QueryTypeLibrary queryTypeLibrary)
        {
            this.intType    = (QueryScalarType)queryTypeLibrary.GetDefaultQueryType(EdmDataTypes.Int32);
            this.stringType = (QueryScalarType)queryTypeLibrary.GetDefaultQueryType(EdmDataTypes.String());

            this.PrimitiveTypes = new List <QueryScalarType>()
            {
                // this is just a sample
                this.intType,
                this.stringType,
                (QueryScalarType)queryTypeLibrary.GetDefaultQueryType(EdmDataTypes.Boolean),
                (QueryScalarType)queryTypeLibrary.GetDefaultQueryType(EdmDataTypes.DateTime()),
                (QueryScalarType)queryTypeLibrary.GetDefaultQueryType(EdmDataTypes.Decimal()),
                (QueryScalarType)queryTypeLibrary.GetDefaultQueryType(EdmDataTypes.Int64),
                (QueryScalarType)queryTypeLibrary.GetDefaultQueryType(EdmDataTypes.Int16),
                (QueryScalarType)queryTypeLibrary.GetDefaultQueryType(EdmDataTypes.Byte),
                (QueryScalarType)queryTypeLibrary.GetDefaultQueryType(EdmDataTypes.Single),
                (QueryScalarType)queryTypeLibrary.GetDefaultQueryType(EdmDataTypes.Double),
                (QueryScalarType)queryTypeLibrary.GetDefaultQueryType(EdmDataTypes.Binary()),
                (QueryScalarType)queryTypeLibrary.GetDefaultQueryType(EdmDataTypes.Guid),
            };
        }
Пример #11
0
        /// <summary>
        /// Factory method to create the <see cref="LinqToAstoriaKeyExpression"/>.
        /// </summary>
        /// <param name="source">The source query.</param>
        /// <param name="keys">The set of key property values.</param>
        /// <returns>The <see cref="QueryExpression"/> with the provided arguments.</returns>
        public static LinqToAstoriaKeyExpression Key(this QueryExpression source, IEnumerable <NamedValue> keys)
        {
            ExceptionUtilities.CheckArgumentNotNull(source, "source");
            ExceptionUtilities.CheckCollectionNotEmpty(keys, "keys");

            QueryType elementType         = QueryType.Unresolved;
            var       queryCollectionType = source.ExpressionType as QueryCollectionType;

            if (queryCollectionType != null)
            {
                elementType = queryCollectionType.ElementType;
            }

            var structuralType = elementType as QueryStructuralType;

            var key = new List <KeyValuePair <QueryProperty, QueryConstantExpression> >();

            foreach (var keyValue in keys)
            {
                QueryScalarType primitiveType = QueryType.UnresolvedPrimitive;
                QueryProperty   queryProperty = QueryProperty.Create(keyValue.Name, primitiveType);

                if (structuralType != null)
                {
                    queryProperty = structuralType.Properties.SingleOrDefault(p => p.Name == keyValue.Name);
                    ExceptionUtilities.CheckObjectNotNull(queryProperty, "Could not find property with name '{0}' on type '{1}'", keyValue.Name, structuralType);

                    primitiveType = queryProperty.PropertyType as QueryScalarType;
                    ExceptionUtilities.CheckObjectNotNull(primitiveType, "Property '{0}' on type '{1}' was not a primitive type", keyValue.Name, structuralType);
                }

                var value = CommonQueryBuilder.Constant(keyValue.Value, primitiveType);
                key.Add(new KeyValuePair <QueryProperty, QueryConstantExpression>(queryProperty, value));
            }

            return(new LinqToAstoriaKeyExpression(source, key, source.ExpressionType));
        }
Пример #12
0
 /// <summary>
 /// Removes any length constraints from the type
 /// </summary>
 /// <param name="type">The type from which to remove the constraints</param>
 /// <returns>The new type with length constraints removed.</returns>
 public QueryScalarType RemoveLengthConstraints(QueryScalarType type)
 {
     return(type);
 }
Пример #13
0
        /// <summary>
        /// Gets the common type to which both types can be promoted.
        /// </summary>
        /// <param name="leftType">First type.</param>
        /// <param name="rightType">Second type.</param>
        /// <returns>
        /// Common type to which both types can be promoted. Throws if unable to find a common type.
        /// </returns>
        public QueryScalarType GetCommonType(QueryScalarType leftType, QueryScalarType rightType)
        {
            Type commonClrType = LinqTypeSemantics.GetCommonType(((QueryClrPrimitiveType)leftType).ClrType, ((QueryClrPrimitiveType)rightType).ClrType);

            return(new QueryClrPrimitiveType(commonClrType, this));
        }
Пример #14
0
        private void UpdateScalarBag(QueryStructuralValue instance, QueryProperty memberProperty, string propertyPath, IEnumerable <NamedValue> namedValues, QueryScalarType scalarElementDataType)
        {
            int i = 0;

            var scalarCollection = new List <QueryValue>();
            List <NamedValue> scalarItemNamedValues = namedValues.Where(pp => pp.Name == propertyPath + "." + i).ToList();

            while (scalarItemNamedValues.Any())
            {
                ExceptionUtilities.Assert(scalarItemNamedValues.Count() < 2, "Should not get more than one value for a scalar Bag item for path '{0}'", propertyPath + "." + i);
                var value = scalarItemNamedValues.Single();
                scalarCollection.Add(scalarElementDataType.CreateValue(value.Value));
                this.unusedNamedValuePaths.Remove(value.Name);

                i++;
                scalarItemNamedValues = namedValues.Where(pp => pp.Name == propertyPath + "." + i).ToList();
            }

            if (scalarCollection.Any())
            {
                this.SetCollectionProperty(instance, memberProperty, scalarCollection);
            }
        }
        private QueryValue VisitScalar(QueryScalarType queryScalarType)
        {
            var scalarResult = this.ResultFragmentStack.Pop();

            return(queryScalarType.CreateValue(scalarResult));
        }
Пример #16
0
        private void UpdateRootScalarBag(QueryCollectionValue instance, IEnumerable <NamedValue> namedValues, QueryScalarType scalarElementDataType)
        {
            int i = 0;

            var scalarCollection = new List <QueryValue>();
            List <NamedValue> scalarItemNamedValues = namedValues.Where(pp => pp.Name == i.ToString(CultureInfo.InvariantCulture)).ToList();

            while (scalarItemNamedValues.Any())
            {
                ExceptionUtilities.Assert(scalarItemNamedValues.Count() < 2, "Should not get more than one value for a scalar Bag item for path '{0}'", i.ToString(CultureInfo.InvariantCulture));
                var value = scalarItemNamedValues.Single();
                scalarCollection.Add(scalarElementDataType.CreateValue(value.Value));
                this.unusedNamedValuePaths.Remove(value.Name);

                i++;
                scalarItemNamedValues = namedValues.Where(pp => pp.Name == i.ToString(CultureInfo.InvariantCulture)).ToList();
            }

            if (scalarCollection.Any())
            {
                this.SetCollectionValue(instance, scalarCollection);
            }
        }
Пример #17
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);
        }