Exemple #1
0
        /// <summary>
        /// "Explode" a root type. (ie) add each member of the type to a flat list of
        /// members for the supertype.
        ///
        /// Type explosion works in a DFS style model. We first walk through the
        /// list of properties for the current type, and "flatten" out the properties
        /// that are themselves "structured". We then target each subtype (recursively)
        /// and perform the same kind of processing.
        ///
        /// Consider a very simple case:
        ///
        ///   Q = (z1 int, z2 date)
        ///   Q2: Q = (z3 string)  -- Q2 is a subtype of Q
        ///   T = (a int, b Q, c date)
        ///   S: T = (d int)  -- read as S is a subtype of T
        ///
        /// The result of flattening T (and S) will be
        ///
        ///   (a int, b.z1 int, b.z2 date, b.z3 string, c date, d int)
        /// </summary>
        /// <param name="rootType">the root type to explode</param>
        private void ExplodeRootStructuredType(RootTypeInfo rootType)
        {
            // Already done??
            if (rootType.FlattenedType != null)
            {
                return;
            }

            //
            // Special handling for root types. Add any special
            // properties that are needed - TypeId, EntitySetId, etc
            //
            if (NeedsTypeIdProperty(rootType))
            {
                rootType.AddPropertyRef(TypeIdPropertyRef.Instance);
                // check for discriminator map; if one exists, use custom discriminator member; otherwise, use default
                if (null != rootType.DiscriminatorMap)
                {
                    rootType.TypeIdKind = TypeIdKind.UserSpecified;
                    rootType.TypeIdType = md.Helper.GetModelTypeUsage(rootType.DiscriminatorMap.DiscriminatorProperty);
                }
                else
                {
                    rootType.TypeIdKind = TypeIdKind.Generated;
                    rootType.TypeIdType = m_stringType;
                }
            }
            if (NeedsEntitySetIdProperty(rootType))
            {
                rootType.AddPropertyRef(EntitySetIdPropertyRef.Instance);
            }
            if (NeedsNullSentinelProperty(rootType))
            {
                rootType.AddPropertyRef(NullSentinelPropertyRef.Instance);
            }

            //
            // Then add members from each type in the hierarchy (including
            // the root type)
            //
            ExplodeRootStructuredTypeHelper(rootType);

            //
            // For entity types, add all the rel-properties now. Note that rel-properties
            // are added after the regular properties of all subtypes
            //
            if (md.TypeSemantics.IsEntityType(rootType.Type))
            {
                AddRelProperties(rootType);
            }

            //
            // We've now gotten all the relevant properties
            // Now let's create a new record type
            //
            CreateFlattenedRecordType(rootType);
        }
Exemple #2
0
        /// <summary>
        /// Get the datatype for a propertyRef. The only concrete classes that we
        /// handle are TypeIdPropertyRef, and BasicPropertyRef.
        /// AllPropertyRef is illegal here.
        /// For BasicPropertyRef, we simply pick up the type from the corresponding
        /// property. For TypeIdPropertyRef, we use "string" as the default type
        /// or the discriminator property type where one is available.
        /// </summary>
        /// <param name="typeInfo">typeinfo of the current type</param>
        /// <param name="p">current property ref</param>
        /// <returns>the datatype of the property</returns>
        private md.TypeUsage GetPropertyType(RootTypeInfo typeInfo, PropertyRef p)
        {
            md.TypeUsage result = null;

            PropertyRef innerProperty = null;

            // Get the "leaf" property first
            while (p is NestedPropertyRef)
            {
                NestedPropertyRef npr = (NestedPropertyRef)p;
                p             = npr.OuterProperty;
                innerProperty = npr.InnerProperty;
            }

            if (p is TypeIdPropertyRef)
            {
                //
                // Get to the innermost type that specifies this typeid (the entity type),
                // get the datatype for the typeid column from that type
                //
                if (innerProperty != null && innerProperty is SimplePropertyRef)
                {
                    md.TypeUsage innerType     = ((SimplePropertyRef)innerProperty).Property.TypeUsage;
                    TypeInfo     innerTypeInfo = GetTypeInfo(innerType);
                    result = innerTypeInfo.RootType.TypeIdType;
                }
                else
                {
                    result = typeInfo.TypeIdType;
                }
            }
            else if (p is EntitySetIdPropertyRef || p is NullSentinelPropertyRef)
            {
                result = m_intType;
            }
            else if (p is RelPropertyRef)
            {
                result = (p as RelPropertyRef).Property.ToEnd.TypeUsage;
            }
            else
            {
                SimplePropertyRef simpleP = p as SimplePropertyRef;
                if (simpleP != null)
                {
                    result = md.Helper.GetModelTypeUsage(simpleP.Property);
                }
            }

            result = GetNewType(result);
            PlanCompiler.Assert(null != result, "unrecognized property type?");
            return(result);
        }
Exemple #3
0
 protected TypeInfo(md.TypeUsage type, TypeInfo superType)
 {
     m_type = type;
     m_immediateSubTypes = new List <TypeInfo>();
     m_superType         = superType;
     if (superType != null)
     {
         // Add myself to my supertype's list of subtypes
         superType.m_immediateSubTypes.Add(this);
         // my supertype's root type is mine as well
         m_rootType = superType.RootType;
     }
 }
        private readonly RootTypeInfo m_rootType;    // the top-most type in this types type hierarchy
        #endregion

        #region Constructors and factory methods

        /// <summary>
        /// Creates type information for a type
        /// </summary>
        /// <param name="type"></param>
        /// <param name="superTypeInfo"></param>
        /// <returns></returns>
        internal static TypeInfo Create(md.TypeUsage type, TypeInfo superTypeInfo, ExplicitDiscriminatorMap discriminatorMap)
        {
            TypeInfo result;
            if (superTypeInfo == null)
            {
                result = new RootTypeInfo(type, discriminatorMap);
            }
            else
            {
                result = new TypeInfo(type, superTypeInfo);
            }
            return result;
        }
 protected TypeInfo(md.TypeUsage type, TypeInfo superType)
 {
     m_type = type;
     m_immediateSubTypes = new List<TypeInfo>();
     m_superType = superType;
     if (superType != null)
     {
         // Add myself to my supertype's list of subtypes
         superType.m_immediateSubTypes.Add(this);
         // my supertype's root type is mine as well
         m_rootType = superType.RootType;
     }
 }
Exemple #6
0
        private readonly RootTypeInfo m_rootType;    // the top-most type in this types type hierarchy
        #endregion

        #region Constructors and factory methods

        /// <summary>
        /// Creates type information for a type
        /// </summary>
        /// <param name="type"></param>
        /// <param name="superTypeInfo"></param>
        /// <returns></returns>
        internal static TypeInfo Create(md.TypeUsage type, TypeInfo superTypeInfo, ExplicitDiscriminatorMap discriminatorMap)
        {
            TypeInfo result;

            if (superTypeInfo == null)
            {
                result = new RootTypeInfo(type, discriminatorMap);
            }
            else
            {
                result = new TypeInfo(type, superTypeInfo);
            }
            return(result);
        }
Exemple #7
0
        /// <summary>
        /// Create the flattened record type for the type.
        /// Walk through the list of property refs, and creates a new field
        /// (which we name as "F1", "F2" etc.) with the required property type.
        ///
        /// We then produce a mapping from the original property (propertyRef really)
        /// to the new property for use in later modules.
        ///
        /// Finally, we identify the TypeId and EntitySetId property if they exist
        /// </summary>
        /// <param name="type"></param>
        private void CreateFlattenedRecordType(RootTypeInfo type)
        {
            //
            // If this type corresponds to an entity type, and that entity type
            // has no subtypes, and that that entity type has no complex properties
            // then simply use the name from that property
            //
            bool usePropertyNamesFromUnderlyingType;

            if (md.TypeSemantics.IsEntityType(type.Type) &&
                type.ImmediateSubTypes.Count == 0)
            {
                usePropertyNamesFromUnderlyingType = true;
            }
            else
            {
                usePropertyNamesFromUnderlyingType = false;
            }


            // Build the record type
            List <KeyValuePair <string, md.TypeUsage> > fieldList = new List <KeyValuePair <string, md.TypeUsage> >();
            HashSet <string> fieldNames = new HashSet <string>();
            int nextFieldId             = 0;

            foreach (PropertyRef p in type.PropertyRefList)
            {
                string fieldName = null;
                if (usePropertyNamesFromUnderlyingType)
                {
                    SimplePropertyRef simpleP = p as SimplePropertyRef;
                    if (simpleP != null)
                    {
                        fieldName = simpleP.Property.Name;
                    }
                }

                if (fieldName == null)
                {
                    fieldName = "F" + nextFieldId.ToString(CultureInfo.InvariantCulture);
                    nextFieldId++;
                }

                // Deal with collisions
                while (fieldNames.Contains(fieldName))
                {
                    fieldName = "F" + nextFieldId.ToString(CultureInfo.InvariantCulture);
                    nextFieldId++;
                }

                md.TypeUsage propertyType = GetPropertyType(type, p);
                fieldList.Add(new KeyValuePair <string, md.TypeUsage>(fieldName, propertyType));
                fieldNames.Add(fieldName);
            }

            type.FlattenedType = TypeHelpers.CreateRowType(fieldList);

            // Now build up the property map
            IEnumerator <PropertyRef> origProps = type.PropertyRefList.GetEnumerator();

            foreach (md.EdmProperty p in type.FlattenedType.Properties)
            {
                if (!origProps.MoveNext())
                {
                    PlanCompiler.Assert(false, "property refs count and flattened type member count mismatch?");
                }
                type.AddPropertyMapping(origProps.Current, p);
            }
        }
Exemple #8
0
        /// <summary>
        /// Helper for ExplodeType.
        /// Walks through each member introduced by the current type, and
        /// adds it onto the "flat" record type being constructed.
        /// We then walk through all subtypes of this type, and process those as
        /// well.
        /// Special handling for Refs: we only add the keys; there is no
        /// need to handle subtypes (since they won't be introducing anything
        /// different)
        /// </summary>
        /// <param name="typeInfo">type in the type hierarchy</param>
        private void ExplodeRootStructuredTypeHelper(TypeInfo typeInfo)
        {
            RootTypeInfo rootType = typeInfo.RootType;

            // Identify the members of this type. For Refs, use the key properties
            // of the target entity type. For all other types, simply use the type
            // members
            IEnumerable typeMembers = null;

            md.RefType refType;
            if (TypeHelpers.TryGetEdmType <md.RefType>(typeInfo.Type, out refType))
            {
                //
                // If this is not the root type, then don't bother adding the keys.
                // the root type has already done this
                //
                if (!typeInfo.IsRootType)
                {
                    return;
                }
                typeMembers = refType.ElementType.KeyMembers;
            }
            else
            {
                typeMembers = TypeHelpers.GetDeclaredStructuralMembers(typeInfo.Type);
            }

            // Walk through all the members of the type
            foreach (md.EdmMember p in typeMembers)
            {
                TypeInfo propertyType = ExplodeType(p.TypeUsage);

                //
                // If we can't find a TypeInfo for this property's type, then it must
                // be a scalar type or a collection type. In either case, we'll
                // build up a SimplePropertyRef
                //
                if (propertyType == null)
                {
                    rootType.AddPropertyRef(new SimplePropertyRef(p));
                }
                else
                {
                    //
                    // We're dealing with a structured type again. Create NestedPropertyRef
                    // for each property of the nested type
                    //
                    foreach (PropertyRef nestedPropInfo in propertyType.PropertyRefList)
                    {
                        rootType.AddPropertyRef(nestedPropInfo.CreateNestedPropertyRef(p));
                    }
                }
            }

            //
            // Process all subtypes now
            //
            foreach (TypeInfo subTypeInfo in typeInfo.ImmediateSubTypes)
            {
                ExplodeRootStructuredTypeHelper(subTypeInfo);
            }
        }
        /// <summary>
        /// Create the flattened record type for the type.
        /// Walk through the list of property refs, and creates a new field
        /// (which we name as "F1", "F2" etc.) with the required property type.
        /// 
        /// We then produce a mapping from the original property (propertyRef really)
        /// to the new property for use in later modules.
        /// 
        /// Finally, we identify the TypeId and EntitySetId property if they exist
        /// </summary>
        /// <param name="type"></param>
        private void CreateFlattenedRecordType(RootTypeInfo type)
        {
            //
            // If this type corresponds to an entity type, and that entity type
            // has no subtypes, and that that entity type has no complex properties
            // then simply use the name from that property
            //
            bool usePropertyNamesFromUnderlyingType;
            if (md.TypeSemantics.IsEntityType(type.Type) &&
                type.ImmediateSubTypes.Count == 0)
            {
                usePropertyNamesFromUnderlyingType = true;
            }
            else
            {
                usePropertyNamesFromUnderlyingType = false;
            }


            // Build the record type
            List<KeyValuePair<string, md.TypeUsage>> fieldList = new List<KeyValuePair<string, md.TypeUsage>>();
            HashSet<string> fieldNames = new HashSet<string>();
            int nextFieldId = 0;
            foreach (PropertyRef p in type.PropertyRefList)
            {
                string fieldName = null;
                if (usePropertyNamesFromUnderlyingType)
                {
                    SimplePropertyRef simpleP = p as SimplePropertyRef;
                    if (simpleP != null)
                    {
                        fieldName = simpleP.Property.Name;
                    }
                }
               
                if (fieldName == null)
                {
                    fieldName = "F" + nextFieldId.ToString(CultureInfo.InvariantCulture);
                    nextFieldId++;
                }
                
                // Deal with collisions
                while (fieldNames.Contains(fieldName))
                {
                    fieldName = "F" + nextFieldId.ToString(CultureInfo.InvariantCulture);
                    nextFieldId++;
                }

                md.TypeUsage propertyType = GetPropertyType(type, p);
                fieldList.Add(new KeyValuePair<string, md.TypeUsage>(fieldName, propertyType));
                fieldNames.Add(fieldName);
            }

            type.FlattenedType = TypeHelpers.CreateRowType(fieldList);

            // Now build up the property map
            IEnumerator<PropertyRef> origProps = type.PropertyRefList.GetEnumerator();
            foreach (md.EdmProperty p in type.FlattenedType.Properties)
            {
                if (!origProps.MoveNext())
                {
                    PlanCompiler.Assert(false, "property refs count and flattened type member count mismatch?");
                }
                type.AddPropertyMapping(origProps.Current, p);
            }
        }
        /// <summary>
        /// "Explode" a root type. (ie) add each member of the type to a flat list of 
        /// members for the supertype. 
        /// 
        /// Type explosion works in a DFS style model. We first walk through the
        /// list of properties for the current type, and "flatten" out the properties
        /// that are themselves "structured". We then target each subtype (recursively)
        /// and perform the same kind of processing. 
        /// 
        /// Consider a very simple case:
        /// 
        ///   Q = (z1 int, z2 date)
        ///   Q2: Q = (z3 string)  -- Q2 is a subtype of Q
        ///   T = (a int, b Q, c date)
        ///   S: T = (d int)  -- read as S is a subtype of T
        /// 
        /// The result of flattening T (and S) will be
        /// 
        ///   (a int, b.z1 int, b.z2 date, b.z3 string, c date, d int)
        /// </summary>
        /// <param name="rootType">the root type to explode</param>        
        private void ExplodeRootStructuredType(RootTypeInfo rootType)
        {
            // Already done??
            if (rootType.FlattenedType != null)
            {
                return;
            }

            //
            // Special handling for root types. Add any special
            // properties that are needed - TypeId, EntitySetId, etc
            //
            if (NeedsTypeIdProperty(rootType))
            {
                rootType.AddPropertyRef(TypeIdPropertyRef.Instance);
                // check for discriminator map; if one exists, use custom discriminator member; otherwise, use default
                if (null != rootType.DiscriminatorMap)
                {
                    rootType.TypeIdKind = TypeIdKind.UserSpecified;
                    rootType.TypeIdType = md.Helper.GetModelTypeUsage(rootType.DiscriminatorMap.DiscriminatorProperty);
                }
                else
                {
                    rootType.TypeIdKind = TypeIdKind.Generated;
                    rootType.TypeIdType = m_stringType;
                }
            }
            if (NeedsEntitySetIdProperty(rootType))
            {
                rootType.AddPropertyRef(EntitySetIdPropertyRef.Instance);
            }
            if (NeedsNullSentinelProperty(rootType))
            {
                rootType.AddPropertyRef(NullSentinelPropertyRef.Instance);
            }

            //
            // Then add members from each type in the hierarchy (including 
            // the root type)
            //
            ExplodeRootStructuredTypeHelper(rootType);

            //
            // For entity types, add all the rel-properties now. Note that rel-properties
            // are added after the regular properties of all subtypes
            //
            if (md.TypeSemantics.IsEntityType(rootType.Type))
            {
                AddRelProperties(rootType);
            }

            //
            // We've now gotten all the relevant properties
            // Now let's create a new record type
            //
            CreateFlattenedRecordType(rootType);
        }
        /// <summary>
        /// Get the datatype for a propertyRef. The only concrete classes that we 
        /// handle are TypeIdPropertyRef, and BasicPropertyRef. 
        /// AllPropertyRef is illegal here.
        /// For BasicPropertyRef, we simply pick up the type from the corresponding
        /// property. For TypeIdPropertyRef, we use "string" as the default type
        /// or the discriminator property type where one is available.
        /// </summary>
        /// <param name="typeInfo">typeinfo of the current type</param>
        /// <param name="p">current property ref</param>
        /// <returns>the datatype of the property</returns>
        private md.TypeUsage GetPropertyType(RootTypeInfo typeInfo, PropertyRef p)
        {
            md.TypeUsage result = null;

            PropertyRef innerProperty = null;
            // Get the "leaf" property first
            while (p is NestedPropertyRef)
            {
                NestedPropertyRef npr = (NestedPropertyRef)p;
                p = npr.OuterProperty;
                innerProperty = npr.InnerProperty;
            }

            if (p is TypeIdPropertyRef)
            {
                //
                // Get to the innermost type that specifies this typeid (the entity type),
                // get the datatype for the typeid column from that type
                //
                if (innerProperty != null && innerProperty is SimplePropertyRef)
                {
                    md.TypeUsage innerType = ((SimplePropertyRef)innerProperty).Property.TypeUsage;
                    TypeInfo innerTypeInfo = GetTypeInfo(innerType);
                    result = innerTypeInfo.RootType.TypeIdType;
                }
                else
                {
                    result = typeInfo.TypeIdType;
                }
            }
            else if (p is EntitySetIdPropertyRef || p is NullSentinelPropertyRef)
            {
                result = m_intType;
            }
            else if (p is RelPropertyRef)
            {
                result = (p as RelPropertyRef).Property.ToEnd.TypeUsage;
            }
            else
            {
                SimplePropertyRef simpleP = p as SimplePropertyRef;
                if (simpleP != null)
                {
                    result = md.Helper.GetModelTypeUsage(simpleP.Property);
                }
            }

            result = GetNewType(result);
            PlanCompiler.Assert(null != result, "unrecognized property type?");
            return result;
        }