/// <summary> /// Factory method for creating a type usage for underlying type of enum type usage. /// </summary> /// <param name="enumTypeUsage"> Enum type usage used to create an underlying type usage of. </param> /// <returns> Type usage for the underlying enum type. </returns> internal static TypeUsage CreateEnumUnderlyingTypeUsage(TypeUsage enumTypeUsage) { DebugCheck.NotNull(enumTypeUsage); Debug.Assert(TypeSemantics.IsEnumerationType(enumTypeUsage), "enumTypeUsage is not an enumerated type"); return(TypeUsage.Create(Helper.GetUnderlyingEdmTypeForEnumType(enumTypeUsage.EdmType), enumTypeUsage.Facets)); }
internal DbConstantExpression(TypeUsage resultType, object value) : base(DbExpressionKind.Constant, resultType) { Debug.Assert(value != null, "DbConstantExpression value cannot be null"); Debug.Assert(TypeSemantics.IsScalarType(resultType), "DbConstantExpression must have a primitive or enum value"); Debug.Assert(!value.GetType().IsEnum || TypeSemantics.IsEnumerationType(resultType), "value is an enum while the result type is not of enum type."); Debug.Assert(Helper.AsPrimitive(resultType.EdmType).ClrEquivalentType == (value.GetType().IsEnum ? value.GetType().GetEnumUnderlyingType() : value.GetType()), "the type of the value has to match the result type (for enum types only underlying types are compared)."); // binary values should be cloned before use PrimitiveType primitiveType; this._shouldCloneValue = TypeHelpers.TryGetEdmType <PrimitiveType>(resultType, out primitiveType) && primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.Binary; if (this._shouldCloneValue) { // DevDiv#480416: DbConstantExpression with a binary value is not fully immutable // this._value = ((byte[])value).Clone(); } else { this._value = value; } }
internal DbConstantExpression(TypeUsage resultType, object value) : base(DbExpressionKind.Constant, resultType) { DebugCheck.NotNull(value); Debug.Assert(TypeSemantics.IsScalarType(resultType), "DbConstantExpression must have a primitive or enum value"); Debug.Assert( !value.GetType().IsEnum() || TypeSemantics.IsEnumerationType(resultType), "value is an enum while the result type is not of enum type."); Debug.Assert( Helper.AsPrimitive(resultType.EdmType).ClrEquivalentType == (value.GetType().IsEnum() ? value.GetType().GetEnumUnderlyingType() : value.GetType()), "the type of the value has to match the result type (for enum types only underlying types are compared)."); // binary values should be cloned before use PrimitiveType primitiveType; _shouldCloneValue = TypeHelpers.TryGetEdmType(resultType, out primitiveType) && primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.Binary; if (_shouldCloneValue) { // DevDiv#480416: DbConstantExpression with a binary value is not fully immutable // CONSIDER: Adding an immutable Binary type or using System.Data.Linq.Binary _value = ((byte[])value).Clone(); } else { _value = value; } }
internal static TypeUsage GetPrimitiveTypeUsageForScalar(TypeUsage scalarType) { if (!TypeSemantics.IsEnumerationType(scalarType)) { return(scalarType); } return(TypeHelpers.CreateEnumUnderlyingTypeUsage(scalarType)); }
internal MetadataMember ResolveMetadataMemberAccess(MetadataMember qualifier, string name, ErrorContext errCtx) { var fullName = GetFullName(qualifier.Name, name); if (qualifier.MetadataMemberClass == MetadataMemberClass.Namespace) { // // Try resolving as a type. // MetadataType type; if (TryGetTypeFromMetadata(fullName, out type)) { return(type); } // // Try resolving as a function. // MetadataFunctionGroup function; if (TryGetFunctionFromMetadata(qualifier.Name, name, out function)) { return(function); } // // Otherwise, resolve as a namespace. // return(new MetadataNamespace(fullName)); } else if (qualifier.MetadataMemberClass == MetadataMemberClass.Type) { var type = (MetadataType)qualifier; if (TypeSemantics.IsEnumerationType(type.TypeUsage)) { EnumMember member; if (_perspective.TryGetEnumMember( (EnumType)type.TypeUsage.EdmType, name, _parserOptions.NameComparisonCaseInsensitive /*ignoreCase*/, out member)) { Debug.Assert(member != null, "member != null"); Debug.Assert( _parserOptions.NameComparer.Equals(name, member.Name), "_parserOptions.NameComparer.Equals(name, member.Name)"); return(new MetadataEnumMember(fullName, type.TypeUsage, member)); } else { var message = Strings.NotAMemberOfType(name, qualifier.Name); throw EntitySqlException.Create(errCtx, message, null); } } } var message1 = Strings.InvalidMetadataMemberClassResolution( qualifier.Name, qualifier.MetadataMemberClassName, MetadataNamespace.NamespaceClassName); throw EntitySqlException.Create(errCtx, message1, null); }
/// <summary> /// Gets primitive type usage for <paramref name="scalarType" />. /// </summary> /// <param name="scalarType"> Primitive or enum type usage. </param> /// <returns> /// Primitive type usage for <paramref name="scalarType" /> . /// </returns> /// <remarks> /// For enum types a new type usage based on the underlying type will be created. For primitive types /// the value passed to the function will be returned. /// </remarks> internal static TypeUsage GetPrimitiveTypeUsageForScalar(TypeUsage scalarType) { DebugCheck.NotNull(scalarType); Debug.Assert(TypeSemantics.IsScalarType(scalarType), "Primitive or enum type expected."); return(TypeSemantics.IsEnumerationType(scalarType) ? CreateEnumUnderlyingTypeUsage(scalarType) : scalarType); }
private static string GetTypeUsageToken(TypeUsage type) { string result = null; // Dev10#537010: EntityCommand false positive cache hits caused by insufficient parameter type information in cache key // Ensure String types are correctly differentiated. if (ReferenceEquals(type, DbTypeMap.AnsiString)) { result = "AnsiString"; } else if (ReferenceEquals(type, DbTypeMap.AnsiStringFixedLength)) { result = "AnsiStringFixedLength"; } else if (ReferenceEquals(type, DbTypeMap.String)) { result = "String"; } else if (ReferenceEquals(type, DbTypeMap.StringFixedLength)) { result = "StringFixedLength"; } else if (ReferenceEquals(type, DbTypeMap.Xml)) { // Xml is currently mapped to (unicode, variable-length) string, so the TypeUsage // given to the provider is actually a String TypeUsage. Debug.Assert( TypeSemantics.IsPrimitiveType(type, PrimitiveTypeKind.String), "Update GetTypeUsageToken to return 'Xml' for Xml parameters"); result = "String"; } else if (TypeSemantics.IsEnumerationType(type)) { result = type.EdmType.FullName; } else { // String/Xml TypeUsages are the only DbType-derived TypeUsages that carry meaningful facets. // Otherwise, the primitive type name is a sufficient token (note that full name is not required // since model types always have the 'Edm' namespace). Debug.Assert(TypeSemantics.IsPrimitiveType(type), "EntityParameter TypeUsage not a primitive type?"); Debug.Assert( !TypeSemantics.IsPrimitiveType(type, PrimitiveTypeKind.String), "String TypeUsage not derived from DbType.AnsiString, AnsiString, String, StringFixedLength or Xml?"); result = type.EdmType.Name; } return(result); }
internal System.Data.Entity.Core.Query.InternalTrees.Node GetInternalTree( Command targetIqtCommand, IList <System.Data.Entity.Core.Query.InternalTrees.Node> targetIqtArguments) { if (this.m_internalTreeNode == null) { DiscriminatorMap discriminatorMap; Command command = ITreeGenerator.Generate(this.GenerateFunctionView(out discriminatorMap), discriminatorMap); System.Data.Entity.Core.Query.InternalTrees.Node root = command.Root; System.Data.Entity.Core.Query.PlanCompiler.PlanCompiler.Assert(root.Op.OpType == OpType.PhysicalProject, "Expected a physical projectOp at the root of the tree - found " + (object)root.Op.OpType); PhysicalProjectOp op = (PhysicalProjectOp)root.Op; System.Data.Entity.Core.Query.InternalTrees.Node child0 = root.Child0; command.DisableVarVecEnumCaching(); System.Data.Entity.Core.Query.InternalTrees.Node relOpNode = child0; Var computedVar = op.Outputs[0]; if (!Command.EqualTypes(op.ColumnMap.Type, this.FunctionImport.ReturnParameter.TypeUsage)) { TypeUsage typeUsage = ((CollectionType)this.FunctionImport.ReturnParameter.TypeUsage.EdmType).TypeUsage; System.Data.Entity.Core.Query.InternalTrees.Node node1 = command.CreateNode((Op)command.CreateVarRefOp(computedVar)); System.Data.Entity.Core.Query.InternalTrees.Node node2 = command.CreateNode((Op)command.CreateSoftCastOp(typeUsage), node1); System.Data.Entity.Core.Query.InternalTrees.Node varDefListNode = command.CreateVarDefListNode(node2, out computedVar); ProjectOp projectOp = command.CreateProjectOp(computedVar); relOpNode = command.CreateNode((Op)projectOp, relOpNode, varDefListNode); } this.m_internalTreeNode = command.BuildCollect(relOpNode, computedVar); } Dictionary <string, System.Data.Entity.Core.Query.InternalTrees.Node> viewArguments = new Dictionary <string, System.Data.Entity.Core.Query.InternalTrees.Node>(this.m_commandParameters.Length); for (int index = 0; index < this.m_commandParameters.Length; ++index) { DbParameterReferenceExpression commandParameter = this.m_commandParameters[index]; System.Data.Entity.Core.Query.InternalTrees.Node node = targetIqtArguments[index]; if (TypeSemantics.IsEnumerationType(node.Op.Type)) { node = targetIqtCommand.CreateNode((Op)targetIqtCommand.CreateSoftCastOp(TypeHelpers.CreateEnumUnderlyingTypeUsage(node.Op.Type)), node); } viewArguments.Add(commandParameter.ParameterName, node); } return(FunctionImportMappingComposable.FunctionViewOpCopier.Copy(targetIqtCommand, this.m_internalTreeNode, viewArguments)); }
internal MetadataMember ResolveMetadataMemberAccess( MetadataMember qualifier, string name, ErrorContext errCtx) { string fullName = TypeResolver.GetFullName(qualifier.Name, name); if (qualifier.MetadataMemberClass == MetadataMemberClass.Namespace) { MetadataType type; if (this.TryGetTypeFromMetadata(fullName, out type)) { return((MetadataMember)type); } MetadataFunctionGroup functionGroup; if (this.TryGetFunctionFromMetadata(qualifier.Name, name, out functionGroup)) { return((MetadataMember)functionGroup); } return((MetadataMember) new MetadataNamespace(fullName)); } if (qualifier.MetadataMemberClass == MetadataMemberClass.Type) { MetadataType metadataType = (MetadataType)qualifier; if (TypeSemantics.IsEnumerationType(metadataType.TypeUsage)) { EnumMember outMember; if (this._perspective.TryGetEnumMember((EnumType)metadataType.TypeUsage.EdmType, name, this._parserOptions.NameComparisonCaseInsensitive, out outMember)) { return((MetadataMember) new MetadataEnumMember(fullName, metadataType.TypeUsage, outMember)); } string errorMessage = Strings.NotAMemberOfType((object)name, (object)qualifier.Name); throw EntitySqlException.Create(errCtx, errorMessage, (Exception)null); } } string errorMessage1 = Strings.InvalidMetadataMemberClassResolution((object)qualifier.Name, (object)qualifier.MetadataMemberClassName, (object)MetadataNamespace.NamespaceClassName); throw EntitySqlException.Create(errCtx, errorMessage1, (Exception)null); }
internal Node GetInternalTree(Command targetIqtCommand, IList <Node> targetIqtArguments) { if (m_internalTreeNode == null) { DiscriminatorMap discriminatorMap; var tree = GenerateFunctionView(out discriminatorMap); Debug.Assert(tree != null, "tree != null"); // Convert this into an ITree first var itree = ITreeGenerator.Generate(tree, discriminatorMap); var rootProject = itree.Root; // PhysicalProject(RelInput) PlanCompiler.Assert( rootProject.Op.OpType == OpType.PhysicalProject, "Expected a physical projectOp at the root of the tree - found " + rootProject.Op.OpType); var rootProjectOp = (PhysicalProjectOp)rootProject.Op; Debug.Assert(rootProjectOp.Outputs.Count == 1, "rootProjectOp.Outputs.Count == 1"); var rootInput = rootProject.Child0; // the RelInput in PhysicalProject(RelInput) // #554756: VarVec enumerators are not cached on the shared Command instance. itree.DisableVarVecEnumCaching(); // Function import returns a collection, so convert it to a scalar by wrapping into CollectOp. var relNode = rootInput; var relVar = rootProjectOp.Outputs[0]; // ProjectOp does not implement Type property, so get the type from the column map. var functionViewType = rootProjectOp.ColumnMap.Type; if (!Command.EqualTypes(functionViewType, FunctionImport.ReturnParameter.TypeUsage)) { Debug.Assert( TypeSemantics.IsPromotableTo(functionViewType, FunctionImport.ReturnParameter.TypeUsage), "Mapping expression result type must be promotable to the c-space function return type."); // Build "relNode = Project(relNode, SoftCast(relVar))" var expectedCollectionType = (CollectionType)FunctionImport.ReturnParameter.TypeUsage.EdmType; var expectedElementType = expectedCollectionType.TypeUsage; var varRefNode = itree.CreateNode(itree.CreateVarRefOp(relVar)); var castNode = itree.CreateNode(itree.CreateSoftCastOp(expectedElementType), varRefNode); var varDefListNode = itree.CreateVarDefListNode(castNode, out relVar); var projectOp = itree.CreateProjectOp(relVar); relNode = itree.CreateNode(projectOp, relNode, varDefListNode); } // Build "Collect(PhysicalProject(relNode)) m_internalTreeNode = itree.BuildCollect(relNode, relVar); } Debug.Assert(m_internalTreeNode != null, "m_internalTreeNode != null"); // Prepare argument replacement dictionary Debug.Assert(m_commandParameters.Length == targetIqtArguments.Count, "m_commandParameters.Length == targetIqtArguments.Count"); var viewArguments = new Dictionary <string, Node>(m_commandParameters.Length); for (var i = 0; i < m_commandParameters.Length; ++i) { var commandParam = m_commandParameters[i]; var argumentNode = targetIqtArguments[i]; // If function import parameter is of enum type, the argument value for it will be of enum type. We however have // converted enum types to underlying types for m_commandParameters. So we now need to softcast the argument // expression to the underlying type as well. if (TypeSemantics.IsEnumerationType(argumentNode.Op.Type)) { argumentNode = targetIqtCommand.CreateNode( targetIqtCommand.CreateSoftCastOp(TypeHelpers.CreateEnumUnderlyingTypeUsage(argumentNode.Op.Type)), argumentNode); } Debug.Assert( TypeSemantics.IsPromotableTo(argumentNode.Op.Type, commandParam.ResultType), "Argument type must be promotable to parameter type."); viewArguments.Add(commandParam.ParameterName, argumentNode); } return(FunctionViewOpCopier.Copy(targetIqtCommand, m_internalTreeNode, viewArguments)); }
internal static bool IsEnumerationType(TypeUsage type) { return(TypeSemantics.IsEnumerationType(type)); }
private static string GetTypeUsageToken(TypeUsage type) { return(!object.ReferenceEquals((object)type, (object)DbTypeMap.AnsiString) ? (!object.ReferenceEquals((object)type, (object)DbTypeMap.AnsiStringFixedLength) ? (!object.ReferenceEquals((object)type, (object)DbTypeMap.String) ? (!object.ReferenceEquals((object)type, (object)DbTypeMap.StringFixedLength) ? (!object.ReferenceEquals((object)type, (object)DbTypeMap.Xml) ? (!TypeSemantics.IsEnumerationType(type) ? type.EdmType.Name : type.EdmType.FullName) : "String") : "StringFixedLength") : "String") : "AnsiStringFixedLength") : "AnsiString"); }