1 //--------------------------------------------------------------------- 2 // <copyright file="TypeUtils.cs" company="Microsoft"> 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // </copyright> 5 // 6 // @owner Microsoft 7 // @backupOwner Microsoft 8 //--------------------------------------------------------------------- 9 10 using System; 11 using System.Collections.Generic; 12 //using System.Diagnostics; // Please use PlanCompiler.Assert instead of Debug.Assert in this class... 13 14 // It is fine to use Debug.Assert in cases where you assert an obvious thing that is supposed 15 // to prevent from simple mistakes during development (e.g. method argument validation 16 // in cases where it was you who created the variables or the variables had already been validated or 17 // in "else" clauses where due to code changes (e.g. adding a new value to an enum type) the default 18 // "else" block is chosen why the new condition should be treated separately). This kind of asserts are 19 // (can be) helpful when developing new code to avoid simple mistakes but have no or little value in 20 // the shipped product. 21 // PlanCompiler.Assert *MUST* be used to verify conditions in the trees. These would be assumptions 22 // about how the tree was built etc. - in these cases we probably want to throw an exception (this is 23 // what PlanCompiler.Assert does when the condition is not met) if either the assumption is not correct 24 // or the tree was built/rewritten not the way we thought it was. 25 // Use your judgment - if you rather remove an assert than ship it use Debug.Assert otherwise use 26 // PlanCompiler.Assert. 27 28 using System.Globalization; 29 30 using System.Data.Common; 31 using md = System.Data.Metadata.Edm; 32 33 // 34 // This module contains a few utility functions that make it easier to operate 35 // with type metadata 36 // 37 38 namespace System.Data.Query.PlanCompiler 39 { 40 /// <summary> 41 /// This class is used as a Comparer for Types all through the PlanCompiler. 42 /// It has a pretty strict definition of type equality - which pretty much devolves 43 /// to equality of the "Identity" of the Type (not the TypeUsage). 44 /// 45 /// NOTE: Unlike other parts of the query pipeline, record types follow 46 /// a much stricter equality condition here - the field names must be the same, and 47 /// the field types must be equal. 48 /// 49 /// NOTE: Primitive types are considered equal, if their Identities are equal. This doesn't 50 /// take into account any of the facets that are represented external to the type (size, for instance). 51 /// Again, this is different from other parts of the query pipeline; and we're much stricter here 52 /// 53 /// </summary> 54 sealed internal class TypeUsageEqualityComparer : IEqualityComparer<md.TypeUsage> 55 { TypeUsageEqualityComparer()56 private TypeUsageEqualityComparer() { } 57 internal static readonly TypeUsageEqualityComparer Instance = new TypeUsageEqualityComparer(); 58 59 #region IEqualityComparer<TypeUsage> Members 60 Equals(System.Data.Metadata.Edm.TypeUsage x, System.Data.Metadata.Edm.TypeUsage y)61 public bool Equals(System.Data.Metadata.Edm.TypeUsage x, System.Data.Metadata.Edm.TypeUsage y) 62 { 63 if (x == null || y == null) 64 { 65 return false; 66 } 67 68 return TypeUsageEqualityComparer.Equals(x.EdmType, y.EdmType); 69 } 70 GetHashCode(System.Data.Metadata.Edm.TypeUsage obj)71 public int GetHashCode(System.Data.Metadata.Edm.TypeUsage obj) 72 { 73 return obj.EdmType.Identity.GetHashCode(); 74 } 75 76 #endregion 77 Equals(md.EdmType x, md.EdmType y)78 internal static bool Equals(md.EdmType x, md.EdmType y) 79 { 80 return x.Identity.Equals(y.Identity); 81 } 82 } 83 84 internal static class TypeUtils 85 { 86 /// <summary> 87 /// Is this type a UDT? (ie) a structural type supported by the store 88 /// </summary> 89 /// <param name="type">the type in question</param> 90 /// <returns>true, if the type was a UDT</returns> IsUdt(md.TypeUsage type)91 internal static bool IsUdt(md.TypeUsage type) 92 { 93 return IsUdt(type.EdmType); 94 } 95 96 /// <summary> 97 /// Is this type a UDT? (ie) a structural type supported by the store 98 /// </summary> 99 /// <param name="type">the type in question</param> 100 /// <returns>true, if the type was a UDT</returns> IsUdt(md.EdmType type)101 internal static bool IsUdt(md.EdmType type) 102 { 103 #if UDT_SUPPORT 104 // Ideally this should be as simple as: 105 // return TypeUsage.HasExtendedAttribute(type, MetadataConstants.UdtAttribute); 106 // The definition below is 'Type is a ComplexType defined in the store'. 107 return (BuiltInTypeKind.ComplexType == type.BuiltInTypeKind && 108 TypeHelpers.HasExtendedAttribute(type, MetadataConstants.TargetAttribute)); 109 #else 110 return false; 111 #endif 112 } 113 114 /// <summary> 115 /// Is this a structured type? 116 /// Note: Structured, in this context means structured outside the server. 117 /// UDTs for instance, are considered to be scalar types - all WinFS types, 118 /// would by this argument, be scalar types. 119 /// </summary> 120 /// <param name="type">The type to check</param> 121 /// <returns>true, if the type is a structured type</returns> IsStructuredType(md.TypeUsage type)122 internal static bool IsStructuredType(md.TypeUsage type) 123 { 124 return (md.TypeSemantics.IsReferenceType(type) || 125 md.TypeSemantics.IsRowType(type) || 126 md.TypeSemantics.IsEntityType(type) || 127 md.TypeSemantics.IsRelationshipType(type) || 128 (md.TypeSemantics.IsComplexType(type) && !IsUdt(type))); 129 } 130 131 /// <summary> 132 /// Is this type a collection type? 133 /// </summary> 134 /// <param name="type">the current type</param> 135 /// <returns>true, if this is a collection type</returns> IsCollectionType(md.TypeUsage type)136 internal static bool IsCollectionType(md.TypeUsage type) 137 { 138 return md.TypeSemantics.IsCollectionType(type); 139 } 140 141 /// <summary> 142 /// Is this type an enum type? 143 /// </summary> 144 /// <param name="type">the current type</param> 145 /// <returns>true, if this is an enum type</returns> IsEnumerationType(md.TypeUsage type)146 internal static bool IsEnumerationType(md.TypeUsage type) 147 { 148 return md.TypeSemantics.IsEnumerationType(type); 149 } 150 151 /// <summary> 152 /// Create a new collection type based on the supplied element type 153 /// </summary> 154 /// <param name="elementType">element type of the collection</param> 155 /// <returns>the new collection type</returns> CreateCollectionType(md.TypeUsage elementType)156 internal static md.TypeUsage CreateCollectionType(md.TypeUsage elementType) 157 { 158 return TypeHelpers.CreateCollectionTypeUsage(elementType); 159 } 160 } 161 } 162