//--------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Collections.Generic; using System.Data.Common; using System.Data.Spatial; using System.Diagnostics; using System.Threading; namespace System.Data.Metadata.Edm { internal class EdmProviderManifest : DbProviderManifest { /// /// The ConcurrencyMode Facet Name /// internal const string ConcurrencyModeFacetName = "ConcurrencyMode"; /// /// The StoreGeneratedPattern Facet Name /// internal const string StoreGeneratedPatternFacetName = "StoreGeneratedPattern"; private Dictionary> _facetDescriptions; private System.Collections.ObjectModel.ReadOnlyCollection _primitiveTypes; private System.Collections.ObjectModel.ReadOnlyCollection _functions; private static EdmProviderManifest _instance = new EdmProviderManifest(); private System.Collections.ObjectModel.ReadOnlyCollection[] _promotionTypes; static TypeUsage[] _canonicalModelTypes; internal const byte MaximumDecimalPrecision = Byte.MaxValue; internal const byte MaximumDateTimePrecision = Byte.MaxValue; /// /// A private constructor to prevent other places from instantiating this class /// private EdmProviderManifest() { } /// /// Gets the EDM provider manifest singleton instance /// internal static EdmProviderManifest Instance { get { return _instance; } } /// /// Returns the namespace used by this provider manifest /// public override string NamespaceName { get { return EdmConstants.EdmNamespace; } } /// /// Store version hint /// internal string Token { // we shouldn't throw exception on properties get { return String.Empty; } } /// /// Returns the list of all the canonical functions /// /// public override System.Collections.ObjectModel.ReadOnlyCollection GetStoreFunctions() { InitializeCanonicalFunctions(); return _functions; } /// /// Returns all the FacetDescriptions for a particular type /// /// the type to return FacetDescriptions for. /// The FacetDescriptions for the type given. public override System.Collections.ObjectModel.ReadOnlyCollection GetFacetDescriptions(EdmType type) { Debug.Assert(type is PrimitiveType, "EdmProviderManifest.GetFacetDescriptions(): Argument is not a PrimitiveType"); InitializeFacetDescriptions(); // Some types may not have facets, so just try to get them, if there aren't any, just return an empty list System.Collections.ObjectModel.ReadOnlyCollection collection = null; if (_facetDescriptions.TryGetValue(type as PrimitiveType, out collection)) { return collection; } return Helper.EmptyFacetDescriptionEnumerable; } /// /// Returns a primitive type from this manifest having the specified primitive type kind /// /// The value specifying the kind of primitive type to return /// A primitive type having the given primitive type kind public PrimitiveType GetPrimitiveType(PrimitiveTypeKind primitiveTypeKind) { InitializePrimitiveTypes(); return _primitiveTypes[(int)primitiveTypeKind]; } /// /// Boostrapping all the primitive types for the EDM Provider Manifest /// private void InitializePrimitiveTypes() { if (_primitiveTypes != null) { return; } PrimitiveType[] primitiveTypes = new PrimitiveType[EdmConstants.NumPrimitiveTypes]; primitiveTypes[(int)PrimitiveTypeKind.Binary] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.Boolean] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.Byte] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.DateTime] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.Decimal] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.Double] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.Single] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.Guid] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.Int16] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.Int32] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.Int64] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.SByte] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.String] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.Time] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.DateTimeOffset] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.Geometry] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.GeometryPoint] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.GeometryLineString] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.GeometryPolygon] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.GeometryMultiPoint] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.GeometryMultiLineString] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.GeometryMultiPolygon] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.GeometryCollection] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.Geography] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.GeographyPoint] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.GeographyLineString] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.GeographyPolygon] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.GeographyMultiPoint] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.GeographyMultiLineString] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.GeographyMultiPolygon] = new PrimitiveType(); primitiveTypes[(int)PrimitiveTypeKind.GeographyCollection] = new PrimitiveType(); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Binary], PrimitiveTypeKind.Binary, EdmConstants.Binary, typeof(Byte[])); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Boolean], PrimitiveTypeKind.Boolean, EdmConstants.Boolean, typeof(Boolean)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Byte], PrimitiveTypeKind.Byte, EdmConstants.Byte, typeof(Byte)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.DateTime], PrimitiveTypeKind.DateTime, EdmConstants.DateTime, typeof(DateTime)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Decimal], PrimitiveTypeKind.Decimal, EdmConstants.Decimal, typeof(Decimal)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Double], PrimitiveTypeKind.Double, EdmConstants.Double, typeof(Double)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Single], PrimitiveTypeKind.Single, EdmConstants.Single, typeof(Single)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Guid], PrimitiveTypeKind.Guid, EdmConstants.Guid, typeof(Guid)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Int16], PrimitiveTypeKind.Int16, EdmConstants.Int16, typeof(Int16)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Int32], PrimitiveTypeKind.Int32, EdmConstants.Int32, typeof(Int32)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Int64], PrimitiveTypeKind.Int64, EdmConstants.Int64, typeof(Int64)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.SByte], PrimitiveTypeKind.SByte, EdmConstants.SByte, typeof(SByte)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.String], PrimitiveTypeKind.String, EdmConstants.String, typeof(String)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Time], PrimitiveTypeKind.Time, EdmConstants.Time, typeof(TimeSpan)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.DateTimeOffset], PrimitiveTypeKind.DateTimeOffset, EdmConstants.DateTimeOffset, typeof(DateTimeOffset)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Geography], PrimitiveTypeKind.Geography, EdmConstants.Geography, typeof(DbGeography)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.GeographyPoint], PrimitiveTypeKind.GeographyPoint, EdmConstants.GeographyPoint, typeof(DbGeography)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.GeographyLineString], PrimitiveTypeKind.GeographyLineString, EdmConstants.GeographyLineString, typeof(DbGeography)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.GeographyPolygon], PrimitiveTypeKind.GeographyPolygon, EdmConstants.GeographyPolygon, typeof(DbGeography)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.GeographyMultiPoint], PrimitiveTypeKind.GeographyMultiPoint, EdmConstants.GeographyMultiPoint, typeof(DbGeography)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.GeographyMultiLineString], PrimitiveTypeKind.GeographyMultiLineString, EdmConstants.GeographyMultiLineString, typeof(DbGeography)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.GeographyMultiPolygon], PrimitiveTypeKind.GeographyMultiPolygon, EdmConstants.GeographyMultiPolygon, typeof(DbGeography)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.GeographyCollection], PrimitiveTypeKind.GeographyCollection, EdmConstants.GeographyCollection, typeof(DbGeography)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.Geometry], PrimitiveTypeKind.Geometry, EdmConstants.Geometry, typeof(DbGeometry)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.GeometryPoint], PrimitiveTypeKind.GeometryPoint, EdmConstants.GeometryPoint, typeof(DbGeometry)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.GeometryLineString], PrimitiveTypeKind.GeometryLineString, EdmConstants.GeometryLineString, typeof(DbGeometry)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.GeometryPolygon], PrimitiveTypeKind.GeometryPolygon, EdmConstants.GeometryPolygon, typeof(DbGeometry)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.GeometryMultiPoint], PrimitiveTypeKind.GeometryMultiPoint, EdmConstants.GeometryMultiPoint, typeof(DbGeometry)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.GeometryMultiLineString], PrimitiveTypeKind.GeometryMultiLineString, EdmConstants.GeometryMultiLineString, typeof(DbGeometry)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.GeometryMultiPolygon], PrimitiveTypeKind.GeometryMultiPolygon, EdmConstants.GeometryMultiPolygon, typeof(DbGeometry)); InitializePrimitiveType(primitiveTypes[(int)PrimitiveTypeKind.GeometryCollection], PrimitiveTypeKind.GeometryCollection, EdmConstants.GeometryCollection, typeof(DbGeometry)); // Set all primitive types to be readonly foreach (PrimitiveType primitiveType in primitiveTypes) { primitiveType.ProviderManifest = this; primitiveType.SetReadOnly(); } System.Collections.ObjectModel.ReadOnlyCollection readOnlyTypes = new System.Collections.ObjectModel.ReadOnlyCollection(primitiveTypes); // Set the result to _primitiveTypes at the end Interlocked.CompareExchange>(ref _primitiveTypes, readOnlyTypes, null); } /// /// Initialize all the primitive type with the given primitive type kind and name /// /// The primitive type to initialize /// Type of the primitive type which is getting initialized /// name of the built in type /// the CLR Type of that maps to the EDM PrimitiveType private void InitializePrimitiveType(PrimitiveType primitiveType, PrimitiveTypeKind primitiveTypeKind, string name, Type clrType) { // Only null types are not abstract and they are sealed, all others are abstract and unsealed EdmType.Initialize(primitiveType, name, EdmConstants.EdmNamespace, DataSpace.CSpace, true /* isabstract */, null /* baseType */); PrimitiveType.Initialize(primitiveType, primitiveTypeKind, true, // isDefault this); Debug.Assert(clrType == primitiveType.ClrEquivalentType, "ClrEquivalentType mismatch"); } /// /// Boostrapping all the facet descriptions for the EDM Provider Manifest /// private void InitializeFacetDescriptions() { if (_facetDescriptions != null) { return; } // Ensure the primitive types are there InitializePrimitiveTypes(); // Create the dictionary of facet descriptions Dictionary> facetDescriptions = new Dictionary>(); // String facets FacetDescription[] list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.String); PrimitiveType applicableType = _primitiveTypes[(int)PrimitiveTypeKind.String]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); // Binary facets list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.Binary); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.Binary]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); // DateTime facets list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.DateTime); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.DateTime]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); // Time facets list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.Time); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.Time]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); // DateTimeOffset facets list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.DateTimeOffset); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.DateTimeOffset]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); // Decimal facets list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.Decimal); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.Decimal]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); // Spatial facets list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.Geography); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.Geography]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.GeographyPoint); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.GeographyPoint]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.GeographyLineString); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.GeographyLineString]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.GeographyPolygon); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.GeographyPolygon]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.GeographyMultiPoint); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.GeographyMultiPoint]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.GeographyMultiLineString); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.GeographyMultiLineString]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.GeographyMultiPolygon); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.GeographyMultiPolygon]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.GeographyCollection); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.GeographyCollection]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.Geometry); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.Geometry]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.GeometryPoint); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.GeometryPoint]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.GeometryLineString); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.GeometryLineString]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.GeometryPolygon); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.GeometryPolygon]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.GeometryMultiPoint); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.GeometryMultiPoint]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.GeometryMultiLineString); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.GeometryMultiLineString]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.GeometryMultiPolygon); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.GeometryMultiPolygon]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); list = EdmProviderManifest.GetInitialFacetDescriptions(PrimitiveTypeKind.GeometryCollection); applicableType = _primitiveTypes[(int)PrimitiveTypeKind.GeometryCollection]; facetDescriptions.Add(applicableType, Array.AsReadOnly(list)); // Set the result to _facetDescriptions at the end Interlocked.CompareExchange>>(ref _facetDescriptions, facetDescriptions, null); } internal static FacetDescription[] GetInitialFacetDescriptions(PrimitiveTypeKind primitiveTypeKind) { FacetDescription[] list; switch (primitiveTypeKind) { case PrimitiveTypeKind.String: { list = new FacetDescription[3]; list[0] = (new FacetDescription(DbProviderManifest.MaxLengthFacetName, MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Int32), 0, Int32.MaxValue, null)); list[1] = (new FacetDescription(DbProviderManifest.UnicodeFacetName, MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Boolean), null, null, null)); list[2] = (new FacetDescription(DbProviderManifest.FixedLengthFacetName, MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Boolean), null, null, null)); return list; } case PrimitiveTypeKind.Binary: { list = new FacetDescription[2]; list[0] = (new FacetDescription(DbProviderManifest.MaxLengthFacetName, MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Int32), 0, Int32.MaxValue, null)); list[1] = (new FacetDescription(DbProviderManifest.FixedLengthFacetName, MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Boolean), null, null, null)); return list; } case PrimitiveTypeKind.DateTime: { list = new FacetDescription[1]; list[0] = (new FacetDescription(DbProviderManifest.PrecisionFacetName, MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Byte), 0, EdmProviderManifest.MaximumDateTimePrecision, null)); return list; } case PrimitiveTypeKind.Time: { list = new FacetDescription[1]; list[0] = (new FacetDescription(DbProviderManifest.PrecisionFacetName, MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Byte), 0, EdmProviderManifest.MaximumDateTimePrecision, TypeUsage.DefaultDateTimePrecisionFacetValue)); return list; } case PrimitiveTypeKind.DateTimeOffset: { list = new FacetDescription[1]; list[0] = (new FacetDescription(DbProviderManifest.PrecisionFacetName, MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Byte), 0, EdmProviderManifest.MaximumDateTimePrecision, TypeUsage.DefaultDateTimePrecisionFacetValue)); return list; } case PrimitiveTypeKind.Decimal: { list = new FacetDescription[2]; list[0] = (new FacetDescription(DbProviderManifest.PrecisionFacetName, MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Byte), 1, EdmProviderManifest.MaximumDecimalPrecision, null)); list[1] = (new FacetDescription(DbProviderManifest.ScaleFacetName, MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Byte), 0, EdmProviderManifest.MaximumDecimalPrecision, null)); return list; } case PrimitiveTypeKind.Geometry: case PrimitiveTypeKind.GeometryPoint: case PrimitiveTypeKind.GeometryLineString: case PrimitiveTypeKind.GeometryPolygon: case PrimitiveTypeKind.GeometryMultiPoint: case PrimitiveTypeKind.GeometryMultiLineString: case PrimitiveTypeKind.GeometryMultiPolygon: case PrimitiveTypeKind.GeometryCollection: { list = new FacetDescription[2]; list[0] = (new FacetDescription(DbProviderManifest.SridFacetName, MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Int32), 0, Int32.MaxValue, DbGeometry.DefaultCoordinateSystemId)); list[1] = (new FacetDescription(DbProviderManifest.IsStrictFacetName, MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Boolean), null, null, true)); return list; } case PrimitiveTypeKind.Geography: case PrimitiveTypeKind.GeographyPoint: case PrimitiveTypeKind.GeographyLineString: case PrimitiveTypeKind.GeographyPolygon: case PrimitiveTypeKind.GeographyMultiPoint: case PrimitiveTypeKind.GeographyMultiLineString: case PrimitiveTypeKind.GeographyMultiPolygon: case PrimitiveTypeKind.GeographyCollection: { list = new FacetDescription[2]; list[0] = (new FacetDescription(DbProviderManifest.SridFacetName, MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Int32), 0, Int32.MaxValue, DbGeography.DefaultCoordinateSystemId)); list[1] = (new FacetDescription(DbProviderManifest.IsStrictFacetName, MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.Boolean), null, null, true)); return list; } default: return null; } } /// /// Boostrapping all the canonical functions for the EDM Provider Manifest /// private void InitializeCanonicalFunctions() { if (_functions != null) { return; } // Ensure primitive types are available InitializePrimitiveTypes(); EdmProviderManifestFunctionBuilder functions = new EdmProviderManifestFunctionBuilder(_primitiveTypes); PrimitiveTypeKind[] parameterTypes; #region Aggregate Functions // Max, Min parameterTypes = new[] { PrimitiveTypeKind.Byte, PrimitiveTypeKind.DateTime, PrimitiveTypeKind.Decimal, PrimitiveTypeKind.Double, PrimitiveTypeKind.Int16, PrimitiveTypeKind.Int32, PrimitiveTypeKind.Int64, PrimitiveTypeKind.SByte, PrimitiveTypeKind.Single, PrimitiveTypeKind.String, PrimitiveTypeKind.Binary, PrimitiveTypeKind.Time, PrimitiveTypeKind.DateTimeOffset }; functions.ForTypes(parameterTypes, type => functions.AddAggregate("Max", type)); functions.ForTypes(parameterTypes, type => functions.AddAggregate("Min", type)); // Avg, Sum parameterTypes = new[] { PrimitiveTypeKind.Decimal, PrimitiveTypeKind.Double, PrimitiveTypeKind.Int32, PrimitiveTypeKind.Int64 }; functions.ForTypes(parameterTypes, type => functions.AddAggregate("Avg", type)); functions.ForTypes(parameterTypes, type => functions.AddAggregate("Sum", type)); // STDEV, STDEVP, VAR, VARP parameterTypes = new[] { PrimitiveTypeKind.Decimal, PrimitiveTypeKind.Double, PrimitiveTypeKind.Int32, PrimitiveTypeKind.Int64}; functions.ForTypes(parameterTypes, type => functions.AddAggregate(PrimitiveTypeKind.Double, "StDev", type)); functions.ForTypes(parameterTypes, type => functions.AddAggregate(PrimitiveTypeKind.Double, "StDevP", type)); functions.ForTypes(parameterTypes, type => functions.AddAggregate(PrimitiveTypeKind.Double, "Var", type)); functions.ForTypes(parameterTypes, type => functions.AddAggregate(PrimitiveTypeKind.Double, "VarP", type)); // Count and Big Count must be supported for all edm types, except the strong spatial types. functions.ForAllBasePrimitiveTypes(type => functions.AddAggregate(PrimitiveTypeKind.Int32, "Count", type)); functions.ForAllBasePrimitiveTypes(type => functions.AddAggregate(PrimitiveTypeKind.Int64, "BigCount", type)); #endregion #region String Functions functions.AddFunction(PrimitiveTypeKind.String, "Trim", PrimitiveTypeKind.String, "stringArgument"); functions.AddFunction(PrimitiveTypeKind.String, "RTrim", PrimitiveTypeKind.String, "stringArgument"); functions.AddFunction(PrimitiveTypeKind.String, "LTrim", PrimitiveTypeKind.String, "stringArgument"); functions.AddFunction(PrimitiveTypeKind.String, "Concat", PrimitiveTypeKind.String, "string1", PrimitiveTypeKind.String, "string2"); functions.AddFunction(PrimitiveTypeKind.Int32, "Length", PrimitiveTypeKind.String, "stringArgument"); // Substring, Left, Right overloads parameterTypes = new[] { PrimitiveTypeKind.Byte, PrimitiveTypeKind.Int16, PrimitiveTypeKind.Int32, PrimitiveTypeKind.Int64, PrimitiveTypeKind.SByte }; functions.ForTypes(parameterTypes, type => functions.AddFunction(PrimitiveTypeKind.String, "Substring", PrimitiveTypeKind.String, "stringArgument", type, "start", type, "length")); functions.ForTypes(parameterTypes, type => functions.AddFunction(PrimitiveTypeKind.String, "Left", PrimitiveTypeKind.String, "stringArgument", type, "length")); functions.ForTypes(parameterTypes, type => functions.AddFunction(PrimitiveTypeKind.String, "Right", PrimitiveTypeKind.String, "stringArgument", type, "length")); functions.AddFunction(PrimitiveTypeKind.String, "Replace", PrimitiveTypeKind.String, "stringArgument", PrimitiveTypeKind.String, "toReplace", PrimitiveTypeKind.String, "replacement"); functions.AddFunction(PrimitiveTypeKind.Int32, "IndexOf", PrimitiveTypeKind.String, "searchString", PrimitiveTypeKind.String, "stringToFind"); functions.AddFunction(PrimitiveTypeKind.String, "ToUpper", PrimitiveTypeKind.String, "stringArgument"); functions.AddFunction(PrimitiveTypeKind.String, "ToLower", PrimitiveTypeKind.String, "stringArgument"); functions.AddFunction(PrimitiveTypeKind.String, "Reverse", PrimitiveTypeKind.String, "stringArgument"); functions.AddFunction(PrimitiveTypeKind.Boolean, "Contains", PrimitiveTypeKind.String, "searchedString", PrimitiveTypeKind.String, "searchedForString"); functions.AddFunction(PrimitiveTypeKind.Boolean, "StartsWith", PrimitiveTypeKind.String, "stringArgument", PrimitiveTypeKind.String, "prefix"); functions.AddFunction(PrimitiveTypeKind.Boolean, "EndsWith", PrimitiveTypeKind.String, "stringArgument", PrimitiveTypeKind.String, "suffix"); #endregion #region DateTime Functions PrimitiveTypeKind[] dateTimeParameterTypes = { PrimitiveTypeKind.DateTimeOffset, PrimitiveTypeKind.DateTime }; functions.ForTypes(dateTimeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "Year", type, "dateValue")); functions.ForTypes(dateTimeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "Month", type, "dateValue")); functions.ForTypes(dateTimeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "Day", type, "dateValue")); functions.ForTypes(dateTimeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "DayOfYear", type, "dateValue")); PrimitiveTypeKind[] timeParameterTypes = { PrimitiveTypeKind.DateTimeOffset, PrimitiveTypeKind.DateTime, PrimitiveTypeKind.Time }; functions.ForTypes(timeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "Hour", type, "timeValue")); functions.ForTypes(timeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "Minute", type, "timeValue")); functions.ForTypes(timeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "Second", type, "timeValue")); functions.ForTypes(timeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "Millisecond", type, "timeValue")); functions.AddFunction(PrimitiveTypeKind.DateTime, "CurrentDateTime"); functions.AddFunction(PrimitiveTypeKind.DateTimeOffset, "CurrentDateTimeOffset"); functions.AddFunction(PrimitiveTypeKind.Int32, "GetTotalOffsetMinutes", PrimitiveTypeKind.DateTimeOffset, "dateTimeOffsetArgument"); functions.AddFunction(PrimitiveTypeKind.DateTime, "CurrentUtcDateTime"); //TruncateTime functions.ForTypes(dateTimeParameterTypes, type => functions.AddFunction(type, "TruncateTime", type, "dateValue")); //DateTime constructor functions.AddFunction(PrimitiveTypeKind.DateTime, "CreateDateTime", PrimitiveTypeKind.Int32, "year", PrimitiveTypeKind.Int32, "month", PrimitiveTypeKind.Int32, "day", PrimitiveTypeKind.Int32, "hour", PrimitiveTypeKind.Int32, "minute", PrimitiveTypeKind.Double, "second"); //DateTimeOffset constructor functions.AddFunction(PrimitiveTypeKind.DateTimeOffset, "CreateDateTimeOffset", PrimitiveTypeKind.Int32, "year", PrimitiveTypeKind.Int32, "month", PrimitiveTypeKind.Int32, "day", PrimitiveTypeKind.Int32, "hour", PrimitiveTypeKind.Int32, "minute", PrimitiveTypeKind.Double, "second", PrimitiveTypeKind.Int32, "timeZoneOffset"); //Time constructor functions.AddFunction(PrimitiveTypeKind.Time, "CreateTime", PrimitiveTypeKind.Int32, "hour", PrimitiveTypeKind.Int32, "minute", PrimitiveTypeKind.Double, "second"); //Date and time addition functions functions.ForTypes(dateTimeParameterTypes, type => functions.AddFunction(type, "AddYears", type, "dateValue", PrimitiveTypeKind.Int32, "addValue")); functions.ForTypes(dateTimeParameterTypes, type => functions.AddFunction(type, "AddMonths", type, "dateValue", PrimitiveTypeKind.Int32, "addValue")); functions.ForTypes(dateTimeParameterTypes, type => functions.AddFunction(type, "AddDays", type, "dateValue", PrimitiveTypeKind.Int32, "addValue")); functions.ForTypes(timeParameterTypes, type => functions.AddFunction(type, "AddHours", type, "timeValue", PrimitiveTypeKind.Int32, "addValue")); functions.ForTypes(timeParameterTypes, type => functions.AddFunction(type, "AddMinutes", type, "timeValue", PrimitiveTypeKind.Int32, "addValue")); functions.ForTypes(timeParameterTypes, type => functions.AddFunction(type, "AddSeconds", type, "timeValue", PrimitiveTypeKind.Int32, "addValue")); functions.ForTypes(timeParameterTypes, type => functions.AddFunction(type, "AddMilliseconds", type, "timeValue", PrimitiveTypeKind.Int32, "addValue")); functions.ForTypes(timeParameterTypes, type => functions.AddFunction(type, "AddMicroseconds", type, "timeValue", PrimitiveTypeKind.Int32, "addValue")); functions.ForTypes(timeParameterTypes, type => functions.AddFunction(type, "AddNanoseconds", type, "timeValue", PrimitiveTypeKind.Int32, "addValue")); // Date and time diff functions functions.ForTypes(dateTimeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "DiffYears", type, "dateValue1", type, "dateValue2")); functions.ForTypes(dateTimeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "DiffMonths", type, "dateValue1", type, "dateValue2")); functions.ForTypes(dateTimeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "DiffDays", type, "dateValue1", type, "dateValue2")); functions.ForTypes(timeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "DiffHours", type, "timeValue1", type, "timeValue2")); functions.ForTypes(timeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "DiffMinutes", type, "timeValue1", type, "timeValue2")); functions.ForTypes(timeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "DiffSeconds", type, "timeValue1", type, "timeValue2")); functions.ForTypes(timeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "DiffMilliseconds", type, "timeValue1", type, "timeValue2")); functions.ForTypes(timeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "DiffMicroseconds", type, "timeValue1", type, "timeValue2")); functions.ForTypes(timeParameterTypes, type => functions.AddFunction(PrimitiveTypeKind.Int32, "DiffNanoseconds", type, "timeValue1", type, "timeValue2")); #endregion // DateTime Functions #region Math Functions // Overloads for ROUND, FLOOR, CEILING functions parameterTypes = new[] { PrimitiveTypeKind.Single, PrimitiveTypeKind.Double, PrimitiveTypeKind.Decimal }; functions.ForTypes(parameterTypes, type => functions.AddFunction(type, "Round", type, "value")); functions.ForTypes(parameterTypes, type => functions.AddFunction(type, "Floor", type, "value")); functions.ForTypes(parameterTypes, type => functions.AddFunction(type, "Ceiling", type, "value")); // Overloads for ROUND, TRUNCATE parameterTypes = new [] { PrimitiveTypeKind.Double, PrimitiveTypeKind.Decimal }; functions.ForTypes(parameterTypes, type => functions.AddFunction(type, "Round", type, "value", PrimitiveTypeKind.Int32, "digits")); functions.ForTypes(parameterTypes, type => functions.AddFunction(type, "Truncate", type, "value", PrimitiveTypeKind.Int32, "digits")); // Overloads for ABS functions parameterTypes = new[] { PrimitiveTypeKind.Decimal, PrimitiveTypeKind.Double, PrimitiveTypeKind.Int16, PrimitiveTypeKind.Int32, PrimitiveTypeKind.Int64, PrimitiveTypeKind.Byte, PrimitiveTypeKind.Single }; functions.ForTypes(parameterTypes, type => functions.AddFunction(type, "Abs", type, "value")); // Overloads for POWER functions PrimitiveTypeKind[] powerFirstParameterTypes = { PrimitiveTypeKind.Decimal, PrimitiveTypeKind.Double, PrimitiveTypeKind.Int32, PrimitiveTypeKind.Int64}; PrimitiveTypeKind[] powerSecondParameterTypes = { PrimitiveTypeKind.Decimal, PrimitiveTypeKind.Double, PrimitiveTypeKind.Int64 }; foreach (PrimitiveTypeKind kind1 in powerFirstParameterTypes) { foreach (PrimitiveTypeKind kind2 in powerSecondParameterTypes) { functions.AddFunction(kind1, "Power", kind1, "baseArgument", kind2, "exponent"); } } #endregion // Math Functions #region Bitwise Functions // Overloads for BitwiseAND, BitwiseNOT, BitwiseOR, BitwiseXOR functions parameterTypes = new[] { PrimitiveTypeKind.Int16, PrimitiveTypeKind.Int32, PrimitiveTypeKind.Int64, PrimitiveTypeKind.Byte }; functions.ForTypes(parameterTypes, type => functions.AddFunction(type, "BitwiseAnd", type, "value1", type, "value2")); functions.ForTypes(parameterTypes, type => functions.AddFunction(type, "BitwiseOr", type, "value1", type, "value2")); functions.ForTypes(parameterTypes, type => functions.AddFunction(type, "BitwiseXor", type, "value1", type, "value2")); functions.ForTypes(parameterTypes, type => functions.AddFunction(type, "BitwiseNot", type, "value")); #endregion #region Misc Functions functions.AddFunction(PrimitiveTypeKind.Guid, "NewGuid"); #endregion // Misc Functions #region Spatial Functions EdmProviderManifestSpatialFunctions.AddFunctions(functions); #endregion System.Collections.ObjectModel.ReadOnlyCollection readOnlyFunctions = functions.ToFunctionCollection(); Interlocked.CompareExchange>(ref _functions, readOnlyFunctions, null); } #region Edm Provider Specific Functionality /// /// Returns the list of super-types for the given primitiveType /// /// /// internal System.Collections.ObjectModel.ReadOnlyCollection GetPromotionTypes(PrimitiveType primitiveType) { InitializePromotableTypes(); return _promotionTypes[(int)primitiveType.PrimitiveTypeKind]; } /// /// Initializes Promotion Type relation /// private void InitializePromotableTypes() { if (null != _promotionTypes) { return; } System.Collections.ObjectModel.ReadOnlyCollection[] promotionTypes = new System.Collections.ObjectModel.ReadOnlyCollection[EdmConstants.NumPrimitiveTypes]; for (int i = 0; i < EdmConstants.NumPrimitiveTypes; i++) { promotionTypes[i] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] { _primitiveTypes[i] }); } // // PrimitiveTypeKind.Byte // promotionTypes[(int)PrimitiveTypeKind.Byte] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] { _primitiveTypes[(int)PrimitiveTypeKind.Byte], _primitiveTypes[(int)PrimitiveTypeKind.Int16], _primitiveTypes[(int)PrimitiveTypeKind.Int32], _primitiveTypes[(int)PrimitiveTypeKind.Int64], _primitiveTypes[(int)PrimitiveTypeKind.Decimal], _primitiveTypes[(int)PrimitiveTypeKind.Single], _primitiveTypes[(int)PrimitiveTypeKind.Double] }); // // PrimitiveTypeKind.Int16 // promotionTypes[(int)PrimitiveTypeKind.Int16] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] { _primitiveTypes[(int)PrimitiveTypeKind.Int16], _primitiveTypes[(int)PrimitiveTypeKind.Int32], _primitiveTypes[(int)PrimitiveTypeKind.Int64], _primitiveTypes[(int)PrimitiveTypeKind.Decimal], _primitiveTypes[(int)PrimitiveTypeKind.Single], _primitiveTypes[(int)PrimitiveTypeKind.Double] }); // // PrimitiveTypeKind.Int32 // promotionTypes[(int)PrimitiveTypeKind.Int32] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] { _primitiveTypes[(int)PrimitiveTypeKind.Int32], _primitiveTypes[(int)PrimitiveTypeKind.Int64], _primitiveTypes[(int)PrimitiveTypeKind.Decimal], _primitiveTypes[(int)PrimitiveTypeKind.Single], _primitiveTypes[(int)PrimitiveTypeKind.Double] }); // // PrimitiveTypeKind.Int64 // promotionTypes[(int)PrimitiveTypeKind.Int64] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] { _primitiveTypes[(int)PrimitiveTypeKind.Int64], _primitiveTypes[(int)PrimitiveTypeKind.Decimal], _primitiveTypes[(int)PrimitiveTypeKind.Single], _primitiveTypes[(int)PrimitiveTypeKind.Double] }); // // PrimitiveTypeKind.Single // promotionTypes[(int)PrimitiveTypeKind.Single] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] { _primitiveTypes[(int)PrimitiveTypeKind.Single], _primitiveTypes[(int)PrimitiveTypeKind.Double] }); InitializeSpatialPromotionGroup( promotionTypes, new PrimitiveTypeKind[] { PrimitiveTypeKind.GeographyPoint, PrimitiveTypeKind.GeographyLineString, PrimitiveTypeKind.GeographyPolygon, PrimitiveTypeKind.GeographyMultiPoint, PrimitiveTypeKind.GeographyMultiLineString, PrimitiveTypeKind.GeographyMultiPolygon, PrimitiveTypeKind.GeographyCollection}, PrimitiveTypeKind.Geography); InitializeSpatialPromotionGroup( promotionTypes, new PrimitiveTypeKind[] { PrimitiveTypeKind.GeometryPoint, PrimitiveTypeKind.GeometryLineString, PrimitiveTypeKind.GeometryPolygon, PrimitiveTypeKind.GeometryMultiPoint, PrimitiveTypeKind.GeometryMultiLineString, PrimitiveTypeKind.GeometryMultiPolygon, PrimitiveTypeKind.GeometryCollection}, PrimitiveTypeKind.Geometry); Interlocked.CompareExchange[]>(ref _promotionTypes, promotionTypes, null); } private void InitializeSpatialPromotionGroup(System.Collections.ObjectModel.ReadOnlyCollection[] promotionTypes, PrimitiveTypeKind[] promotableKinds, PrimitiveTypeKind baseKind) { foreach (PrimitiveTypeKind promotableKind in promotableKinds) { promotionTypes[(int)promotableKind] = new System.Collections.ObjectModel.ReadOnlyCollection(new PrimitiveType[] { _primitiveTypes[(int)promotableKind], _primitiveTypes[(int)baseKind] }); } } internal TypeUsage GetCanonicalModelTypeUsage(PrimitiveTypeKind primitiveTypeKind) { if (null == _canonicalModelTypes) { InitializeCanonicalModelTypes(); } return _canonicalModelTypes[(int)primitiveTypeKind]; } /// /// Initializes Canonical Model Types /// private void InitializeCanonicalModelTypes() { InitializePrimitiveTypes(); TypeUsage[] canonicalTypes = new TypeUsage[EdmConstants.NumPrimitiveTypes]; for (int primitiveTypeIndex = 0; primitiveTypeIndex < EdmConstants.NumPrimitiveTypes; primitiveTypeIndex++) { PrimitiveType primitiveType = _primitiveTypes[primitiveTypeIndex]; TypeUsage typeUsage = TypeUsage.CreateDefaultTypeUsage(primitiveType); Debug.Assert(null != typeUsage, "TypeUsage must not be null"); canonicalTypes[primitiveTypeIndex] = typeUsage; } Interlocked.CompareExchange(ref _canonicalModelTypes, canonicalTypes, null); } #endregion #region DbProviderManifest Interface /// /// Returns all the primitive types supported by the provider manifest /// /// A collection of primitive types public override System.Collections.ObjectModel.ReadOnlyCollection GetStoreTypes() { InitializePrimitiveTypes(); return _primitiveTypes; } public override TypeUsage GetEdmType(TypeUsage storeType) { throw new NotImplementedException(); } public override TypeUsage GetStoreType(TypeUsage edmType) { throw new NotImplementedException(); } internal TypeUsage ForgetScalarConstraints(TypeUsage type) { PrimitiveType primitiveType = type.EdmType as PrimitiveType; Debug.Assert(primitiveType != null, "type argument must be primitive in order to use this function"); if (primitiveType != null) { return GetCanonicalModelTypeUsage(primitiveType.PrimitiveTypeKind); } else { return type; } } /// /// Providers should override this to return information specific to their provider. /// /// This method should never return null. /// /// The name of the information to be retrieved. /// An XmlReader at the begining of the information requested. protected override System.Xml.XmlReader GetDbInformation(string informationType) { throw new NotImplementedException(); } #endregion } }