/// <summary>
        /// Overrides the default equality function. Two SimplePropertyRefs are
        /// equal, if they describe the same property
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            SimplePropertyRef other = obj as SimplePropertyRef;

            return(other != null &&
                   InternalTrees.Command.EqualTypes(m_property.DeclaringType, other.m_property.DeclaringType) &&
                   other.m_property.Name.Equals(this.m_property.Name));
        }
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);
        }
        /// <summary>
        /// Gets the list of key properties for an entity
        /// </summary>
        /// <param name="entityType"></param>
        /// <returns></returns>
        private static PropertyRefList GetKeyProperties(md.EntityType entityType)
        {
            PropertyRefList desiredProperties = new PropertyRefList();

            foreach (md.EdmMember p in entityType.KeyMembers)
            {
                md.EdmProperty edmP = p as md.EdmProperty;
                PlanCompiler.Assert(edmP != null, "EntityType had non-EdmProperty key member?");
                SimplePropertyRef pRef = new SimplePropertyRef(edmP);
                desiredProperties.Add(pRef);
            }
            return(desiredProperties);
        }
Exemple #4
0
        /// <summary>
        /// Get the list of "key" properties (in the flattened type)
        /// </summary>
        /// <returns>the key property equivalents in the flattened type</returns>
        internal IEnumerable <PropertyRef> GetKeyPropertyRefs()
        {
            md.EntityTypeBase entityType = null;
            md.RefType        refType    = null;
            if (TypeHelpers.TryGetEdmType <md.RefType>(m_type, out refType))
            {
                entityType = refType.ElementType;
            }
            else
            {
                entityType = TypeHelpers.GetEdmType <md.EntityTypeBase>(m_type);
            }

            // Walk through the list of keys of the entity type, and find their analogs in the
            // "flattened" type
            foreach (md.EdmMember p in entityType.KeyMembers)
            {
                // Eventually this could be RelationshipEndMember, but currently only properties are suppported as key members
                PlanCompiler.Assert(p is md.EdmProperty, "Non-EdmProperty key members are not supported");
                SimplePropertyRef spr = new SimplePropertyRef(p);
                yield return(spr);
            }
        }
        /// <summary>
        /// Flattens out a constructor into a "flat" record constructor. 
        /// The "flat" record type is looked up for the current constructor's type,
        /// and each property is filled out from the current constructor's fields
        /// </summary>
        /// <param name="op">The NewRecordOp/NewInstanceOp</param>
        /// <param name="n">The current subtree</param>
        /// <returns>the new subtree</returns>
        private Node FlattenConstructor(ScalarOp op, Node n)
        {
            PlanCompiler.Assert(op.OpType == OpType.NewInstance || op.OpType == OpType.NewRecord || op.OpType == OpType.DiscriminatedNewEntity || op.OpType == OpType.NewEntity,
                "unexpected op: " + op.OpType + "?");

            // First visit all my children
            VisitChildren(n);

            // Find the new type corresponding to the type
            TypeInfo typeInfo = m_typeInfo.GetTypeInfo(op.Type);
            md.RowType flatType = typeInfo.FlattenedType;
            NewEntityBaseOp newEntityOp = op as NewEntityBaseOp;

            // Identify the fields
            IEnumerable opFields = null;
            DiscriminatedNewEntityOp discriminatedNewInstanceOp = null;
            if (op.OpType == OpType.NewRecord)
            {
                // Get only those fields that I have values for 
                opFields = ((NewRecordOp)op).Properties;
            }
            else if (op.OpType == OpType.DiscriminatedNewEntity)
            {
                // Get all properties projected by the discriminated new instance op
                discriminatedNewInstanceOp = (DiscriminatedNewEntityOp)op;
                opFields = discriminatedNewInstanceOp.DiscriminatorMap.Properties;
            }
            else
            {
                // Children align with structural members of type for a standard NewInstanceOp
                opFields = TypeHelpers.GetAllStructuralMembers(op.Type);
            }

            // Next, walk through each of my field, and flatten out any field
            // that is structured.
            List<md.EdmProperty> newFields = new List<md.EdmProperty>();
            List<Node> newFieldValues = new List<Node>();

            //
            // NOTE: we expect the type id property and the entityset id properties
            //       to be at the start of the properties collection.
            //
            // Add a typeid property if we need one
            //
            if (typeInfo.HasTypeIdProperty)
            {
                newFields.Add(typeInfo.TypeIdProperty);
                if (null == discriminatedNewInstanceOp)
                {
                    newFieldValues.Add(CreateTypeIdConstant(typeInfo));
                }
                else
                {
                    // first child in DiscriminatedNewInstanceOp is discriminator/typeid
                    Node discriminator = n.Children[0];

                    if (null == typeInfo.RootType.DiscriminatorMap)
                    {
                        // if there are multiple sets (or free-floating constructors) for this type
                        // hierarchy, normalize the discriminator value to expose the standard
                        // '0X' style values
                        discriminator = NormalizeTypeDiscriminatorValues(discriminatedNewInstanceOp, discriminator);
                    }

                    newFieldValues.Add(discriminator);
                }
            }

            //
            // Add an entitysetid property if we need one
            //
            if (typeInfo.HasEntitySetIdProperty)
            {
                newFields.Add(typeInfo.EntitySetIdProperty);

                PlanCompiler.Assert(newEntityOp != null, "unexpected optype:" + op.OpType);
                Node entitySetIdNode = GetEntitySetIdExpr(typeInfo.EntitySetIdProperty, newEntityOp);

                // Get the entity-set-id of the "current" entityset
                newFieldValues.Add(entitySetIdNode);
            }

            // Add a nullability property if we need one
            if (typeInfo.HasNullSentinelProperty)
            {
                newFields.Add(typeInfo.NullSentinelProperty);
                newFieldValues.Add(CreateNullSentinelConstant());
            }

            //
            // first child of discriminatedNewInstanceOp is the typeId; otherwise, the first child is the first property
            //
            int childrenIndex = null == discriminatedNewInstanceOp ? 0 : 1;

            foreach (md.EdmMember opField in opFields)
            {
                Node fieldValue = n.Children[childrenIndex];
                if (TypeUtils.IsStructuredType(md.Helper.GetModelTypeUsage(opField)))
                {
                    // Flatten out nested type
                    md.RowType nestedFlatType = m_typeInfo.GetTypeInfo(md.Helper.GetModelTypeUsage(opField)).FlattenedType;

                    // Find offset of opField in top-level flat type
                    int nestedPropertyOffset = typeInfo.RootType.GetNestedStructureOffset(new SimplePropertyRef(opField));

                    foreach (md.EdmProperty nestedProperty in nestedFlatType.Properties)
                    {
                        // Try to build up an accessor for this property from the input
                        Node nestedPropertyValue = BuildAccessor(fieldValue, nestedProperty);

                        if (null != nestedPropertyValue)
                        {
                            newFields.Add(flatType.Properties[nestedPropertyOffset]);
                            newFieldValues.Add(nestedPropertyValue);
                        }

                        nestedPropertyOffset++;
                    }
                }
                else
                {
                    PropertyRef propRef = new SimplePropertyRef(opField);
                    md.EdmProperty outputTypeProp = typeInfo.GetNewProperty(propRef);

                    newFields.Add(outputTypeProp);

                    newFieldValues.Add(fieldValue);
                }

                childrenIndex++;
            }

            //
            // We've now handled all the regular properties. Now, walk through all the rel properties - 
            // obviously, this only applies for the *NewEntityOps
            //
            if (newEntityOp != null)
            {
                foreach (RelProperty relProp in newEntityOp.RelationshipProperties)
                {
                    Node fieldValue = n.Children[childrenIndex];
                    md.RowType nestedFlatType = m_typeInfo.GetTypeInfo(relProp.ToEnd.TypeUsage).FlattenedType;

                    // Find offset of opField in top-level flat type
                    int nestedPropertyOffset = typeInfo.RootType.GetNestedStructureOffset(new RelPropertyRef(relProp));

                    foreach (md.EdmProperty nestedProperty in nestedFlatType.Properties)
                    {
                        // Try to build up an accessor for this property from the input
                        Node nestedPropertyValue = BuildAccessor(fieldValue, nestedProperty);

                        if (null != nestedPropertyValue)
                        {
                            newFields.Add(flatType.Properties[nestedPropertyOffset]);
                            newFieldValues.Add(nestedPropertyValue);
                        }

                        nestedPropertyOffset++;
                    }
                    childrenIndex++;
                }
            }

            //
            // So, now we have the list of all fields that should make up the 
            // flat type.  Create a new node with them.
            //
            NewRecordOp newOp = m_command.CreateNewRecordOp(typeInfo.FlattenedTypeUsage, newFields);
            Node newNode = m_command.CreateNode(newOp, newFieldValues);

            return newNode;
        }
Exemple #6
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);
            }
        }
        /// <summary>
        /// Get the list of "key" properties (in the flattened type)
        /// </summary>
        /// <returns>the key property equivalents in the flattened type</returns>
        internal IEnumerable<PropertyRef> GetKeyPropertyRefs()
        {
            md.EntityTypeBase entityType = null;
            md.RefType refType = null;
            if (TypeHelpers.TryGetEdmType<md.RefType>(m_type, out refType))
            {
                entityType = refType.ElementType;
            }
            else
            {
                entityType = TypeHelpers.GetEdmType<md.EntityTypeBase>(m_type);
            }

            // Walk through the list of keys of the entity type, and find their analogs in the
            // "flattened" type
            foreach (md.EdmMember p in entityType.KeyMembers)
            {
                // Eventually this could be RelationshipEndMember, but currently only properties are suppported as key members
                PlanCompiler.Assert(p is md.EdmProperty, "Non-EdmProperty key members are not supported");
                SimplePropertyRef spr = new SimplePropertyRef(p);
                yield return spr;
            }
        }
 /// <summary>
 /// Gets the list of key properties for an entity
 /// </summary>
 /// <param name="entityType"></param>
 /// <returns></returns>
 private static PropertyRefList GetKeyProperties(md.EntityType entityType)
 {
     PropertyRefList desiredProperties = new PropertyRefList();
     foreach (md.EdmMember p in entityType.KeyMembers)
     {
         md.EdmProperty edmP = p as md.EdmProperty;
         PlanCompiler.Assert(edmP != null, "EntityType had non-EdmProperty key member?");
         SimplePropertyRef pRef = new SimplePropertyRef(edmP);
         desiredProperties.Add(pRef);
     }
     return desiredProperties;
 }