예제 #1
0
        /// <summary>
        /// Promote the left and right operand types
        /// </summary>
        /// <param name="binaryOperatorKind">the operator kind</param>
        /// <param name="left">the left operand</param>
        /// <param name="right">the right operand</param>
        private static void PromoteOperandTypes(BinaryOperatorKind binaryOperatorKind, ref SingleValueNode left, ref SingleValueNode right)
        {
            IEdmTypeReference leftType  = left.TypeReference;
            IEdmTypeReference rightType = right.TypeReference;

            if (!TypePromotionUtils.PromoteOperandTypes(binaryOperatorKind, ref leftType, ref rightType))
            {
                string leftTypeName  = left.TypeReference == null ? "<null>" : left.TypeReference.ODataFullName();
                string rightTypeName = right.TypeReference == null ? "<null>" : right.TypeReference.ODataFullName();
                throw new ODataException(ODataErrorStrings.MetadataBinder_IncompatibleOperandsError(leftTypeName, rightTypeName, binaryOperatorKind));
            }

            left  = MetadataBindingUtils.ConvertToTypeIfNeeded(left, leftType);
            right = MetadataBindingUtils.ConvertToTypeIfNeeded(right, rightType);
        }
예제 #2
0
 internal static object VerifyAndCoerceUriPrimitiveLiteral(object primitiveValue, IEdmModel model, IEdmTypeReference expectedTypeReference, ODataVersion version)
 {
     ExceptionUtils.CheckArgumentNotNull<object>(primitiveValue, "primitiveValue");
     ExceptionUtils.CheckArgumentNotNull<IEdmModel>(model, "model");
     ExceptionUtils.CheckArgumentNotNull<IEdmTypeReference>(expectedTypeReference, "expectedTypeReference");
     ODataUriNullValue value2 = primitiveValue as ODataUriNullValue;
     if (value2 != null)
     {
         if (!expectedTypeReference.IsNullable)
         {
             throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralNullOnNonNullableType(expectedTypeReference.ODataFullName()));
         }
         IEdmType type = ValidationUtils.ValidateValueTypeName(model, value2.TypeName, expectedTypeReference.Definition.TypeKind);
         if (type.IsSpatial())
         {
             ODataVersionChecker.CheckSpatialValue(version);
         }
         if (!TypePromotionUtils.CanConvertTo(type.ToTypeReference(), expectedTypeReference))
         {
             throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralNullTypeVerificationFailure(expectedTypeReference.ODataFullName(), value2.TypeName));
         }
         value2.TypeName = expectedTypeReference.ODataFullName();
         return value2;
     }
     IEdmPrimitiveTypeReference reference = expectedTypeReference.AsPrimitiveOrNull();
     if (reference == null)
     {
         throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(expectedTypeReference.ODataFullName(), primitiveValue));
     }
     object obj2 = CoerceNumericType(primitiveValue, reference.PrimitiveDefinition());
     if (obj2 != null)
     {
         return obj2;
     }
     Type c = primitiveValue.GetType();
     if (!TypeUtils.GetNonNullableType(EdmLibraryExtensions.GetPrimitiveClrType(reference)).IsAssignableFrom(c))
     {
         throw new ODataException(Microsoft.Data.OData.Strings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(reference.ODataFullName(), primitiveValue));
     }
     return primitiveValue;
 }
예제 #3
0
        /// <summary>
        /// Finds the signature that best matches the arguments
        /// </summary>
        /// <param name="functionName">The name of the function</param>
        /// <param name="argumentTypes">The types of the arguments</param>
        /// <param name="signatures">The signatures to match against</param>
        /// <returns>Returns the matching signature or throws</returns>
        internal static FunctionSignatureWithReturnType MatchSignatureToBuiltInFunction(string functionName, IEdmTypeReference[] argumentTypes, FunctionSignatureWithReturnType[] signatures)
        {
            DebugUtils.CheckNoExternalCallers();
            FunctionSignatureWithReturnType signature;

            // Handle the cases where we don't have type information (null literal, open properties) for ANY of the arguments
            int argumentCount = argumentTypes.Length;

            if (argumentTypes.All(a => a == null) && argumentCount > 0)
            {
                // we specifically want to find just the first function that matches the number of arguments, we don't care about
                // ambiguity here because we're already in an ambiguous case where we don't know what kind of types
                // those arguments are.
                signature = signatures.FirstOrDefault(candidateFunction => candidateFunction.ArgumentTypes.Count() == argumentCount);
                if (signature == null)
                {
                    throw new ODataException(ODataErrorStrings.FunctionCallBinder_CannotFindASuitableOverload(functionName, argumentTypes.Count()));
                }
                else
                {
                    // in this case we can't assert the return type, we can only assert that a function exists... so
                    // we need to set the return type to null.
                    signature = new FunctionSignatureWithReturnType(null, signature.ArgumentTypes);
                }
            }
            else
            {
                signature = TypePromotionUtils.FindBestFunctionSignature(signatures, argumentTypes);
                if (signature == null)
                {
                    throw new ODataException(ODataErrorStrings.MetadataBinder_NoApplicableFunctionFound(
                                                 functionName,
                                                 BuiltInFunctions.BuildFunctionSignatureListDescription(functionName, signatures)));
                }
            }

            return(signature);
        }
예제 #4
0
        /// <summary>
        /// Verifies that the given <paramref name="primitiveValue"/> is or can be coerced to <paramref name="expectedTypeReference"/>, and coerces it if necessary.
        /// </summary>
        /// <param name="primitiveValue">An EDM primitive value to verify.</param>
        /// <param name="model">Model to verify against.</param>
        /// <param name="expectedTypeReference">Expected type reference.</param>
        /// <param name="version">The version to use for reading.</param>
        /// <returns>Coerced version of the <paramref name="primitiveValue"/>.</returns>
        internal static object VerifyAndCoerceUriPrimitiveLiteral(object primitiveValue, IEdmModel model, IEdmTypeReference expectedTypeReference, ODataVersion version)
        {
            DebugUtils.CheckNoExternalCallers();
            ExceptionUtils.CheckArgumentNotNull(primitiveValue, "primitiveValue");
            ExceptionUtils.CheckArgumentNotNull(model, "model");
            ExceptionUtils.CheckArgumentNotNull(expectedTypeReference, "expectedTypeReference");

            // First deal with null literal
            ODataUriNullValue nullValue = primitiveValue as ODataUriNullValue;

            if (nullValue != null)
            {
                if (!expectedTypeReference.IsNullable)
                {
                    throw new ODataException(ODataErrorStrings.ODataUriUtils_ConvertFromUriLiteralNullOnNonNullableType(expectedTypeReference.ODataFullName()));
                }

                // If it was just 'null' on the wire (no typed null) then just take what was expected and use that
                if (nullValue.TypeName == null)
                {
                    nullValue.TypeName = expectedTypeReference.ODataFullName();
                    return(nullValue);
                }

                IEdmType actualResolvedType = TypeNameOracle.ResolveAndValidateTypeName(model, nullValue.TypeName, expectedTypeReference.Definition.TypeKind);
                Debug.Assert(actualResolvedType != null, "This is a primitive-only codepath so actualResolvedType != null.");

                if (actualResolvedType.IsSpatial())
                {
                    ODataVersionChecker.CheckSpatialValue(version);
                }

                if (TypePromotionUtils.CanConvertTo(actualResolvedType.ToTypeReference(), expectedTypeReference))
                {
                    nullValue.TypeName = expectedTypeReference.ODataFullName();
                    return(nullValue);
                }

                throw new ODataException(ODataErrorStrings.ODataUriUtils_ConvertFromUriLiteralNullTypeVerificationFailure(expectedTypeReference.ODataFullName(), nullValue.TypeName));
            }

            // Only other positive case is a numeric primitive that needs to be coerced
            IEdmPrimitiveTypeReference expectedPrimitiveTypeReference = expectedTypeReference.AsPrimitiveOrNull();

            if (expectedPrimitiveTypeReference == null)
            {
                throw new ODataException(ODataErrorStrings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(expectedTypeReference.ODataFullName(), primitiveValue));
            }

            object coercedResult = CoerceNumericType(primitiveValue, expectedPrimitiveTypeReference.PrimitiveDefinition());

            if (coercedResult != null)
            {
                return(coercedResult);
            }

            Type actualType = primitiveValue.GetType();
            Type targetType = TypeUtils.GetNonNullableType(EdmLibraryExtensions.GetPrimitiveClrType(expectedPrimitiveTypeReference));

            // If target type is assignable from actual type, we're OK
            if (targetType.IsAssignableFrom(actualType))
            {
                return(primitiveValue);
            }

            throw new ODataException(ODataErrorStrings.ODataUriUtils_ConvertFromUriLiteralTypeVerificationFailure(expectedPrimitiveTypeReference.ODataFullName(), primitiveValue));
        }