/// <summary> /// VarRefOp handling /// /// Simply passes along the current "desired" properties /// to the corresponding Var /// </summary> /// <param name="op"></param> /// <param name="n"></param> public override void Visit(VarRefOp op, Node n) { if (TypeUtils.IsStructuredType(op.Var.Type)) { // Get the properties that my parent expects from me. PropertyRefList myProps = GetPropertyRefList(n); // Add this onto the list of properties expected from the var itself AddPropertyRefs(op.Var, myProps); } }
/// <summary> /// VarDefOp handling /// /// Pushes the "desired" properties to the /// defining expression /// </summary> /// <param name="op"></param> /// <param name="n"></param> public override void Visit(VarDefOp op, Node n) { if (TypeUtils.IsStructuredType(op.Var.Type)) { PropertyRefList myProps = GetPropertyRefList(op.Var); // Push this down to the expression defining the var AddPropertyRefs(n.Child0, myProps); } VisitChildren(n); }
/// <summary> /// DistinctOp handling /// /// Require all properties out of all structured vars /// </summary> /// <param name="op"></param> /// <param name="n"></param> public override void Visit(DistinctOp op, Node n) { foreach (Var v in op.Keys) { if (TypeUtils.IsStructuredType(v.Type)) { AddPropertyRefs(v, PropertyRefList.All); } } VisitChildren(n); }
/// <summary> /// Default visitor for an Op. /// /// Simply walks through all children looking for Ops of structured /// types, and asks for all their properties. /// </summary> /// <remarks> /// Several of the ScalarOps take the default handling, to simply ask /// for all the children's properties: /// /// AggegateOp /// ArithmeticOp /// CastOp /// ConditionalOp /// ConstantOp /// ElementOp /// ExistsOp /// FunctionOp /// GetRefKeyOp /// LikeOp /// NestAggregateOp /// NewInstanceOp /// NewMultisetOp /// NewRecordOp /// RefOp /// /// They do not exist here to eliminate noise. /// /// Note that the NewRecordOp and the NewInstanceOp could be optimized to only /// push down the appropriate references, but it isn't clear to Murali that the /// complexity is worth it. /// </remarks> /// <param name="n"></param> protected override void VisitDefault(Node n) { // for each child that is a complex type, simply ask for all properties foreach (Node chi in n.Children) { ScalarOp chiOp = chi.Op as ScalarOp; if (chiOp != null && TypeUtils.IsStructuredType(chiOp.Type)) { AddPropertyRefs(chi, PropertyRefList.All); } } VisitChildren(n); }
/// <summary> /// Creates a column map for a column /// </summary> /// <param name="type">column datatype</param> /// <param name="name">column name</param> /// <returns></returns> private ColumnMap CreateColumnMap(md.TypeUsage type, string name) { // For simple types, create a simple column map // Temporarily, handle collections exactly the same way if (!TypeUtils.IsStructuredType(type)) { return(CreateSimpleColumnMap(type, name)); } // At this point, we must be dealing with either a record type, a // complex type, or an entity type return(CreateStructuralColumnMap(type, name)); }
/// <summary> /// PhysicalProjectOp handling /// </summary> /// <param name="op"></param> /// <param name="n"></param> public override void Visit(PhysicalProjectOp op, Node n) { // Insist that we need all properties from all the outputs foreach (Var v in op.Outputs) { if (TypeUtils.IsStructuredType(v.Type)) { AddPropertyRefs(v, PropertyRefList.All); } } // simply visit the children VisitChildren(n); }
/// <summary> /// GroupByOp handling /// </summary> /// <param name="op"></param> /// <param name="n"></param> protected override void VisitGroupByOp(GroupByBaseOp op, Node n) { // First "request" all properties for every key (that is a structured type) foreach (Var v in op.Keys) { if (TypeUtils.IsStructuredType(v.Type)) { AddPropertyRefs(v, PropertyRefList.All); } } // Now visit the aggregate definitions, the key definitions, and // the relop input in that order VisitChildrenReverse(n); }
/// <summary> /// Find the TypeInfo entry for a type. For non-structured types, we always /// return null. For structured types, we return the entry in the typeInfoMap. /// If we don't find one, and the typeInfoMap has already been populated, then we /// assert /// </summary> /// <param name="type">the type to look up</param> /// <returns>the typeinfo for the type (null if we couldn't find one)</returns> internal TypeInfo GetTypeInfo(md.TypeUsage type) { if (!TypeUtils.IsStructuredType(type)) { return(null); } TypeInfo typeInfo = null; if (!m_typeInfoMap.TryGetValue(type, out typeInfo)) { PlanCompiler.Assert(!TypeUtils.IsStructuredType(type) || !m_typeInfoMapPopulated, "cannot find typeInfo for type " + type); } return(typeInfo); }
/// <summary> /// "Explode" a type. (ie) produce a flat record type with one property for each /// scalar property (top-level or nested) of the original type. /// Really deals with structured types, but also /// peels off collection wrappers /// </summary> /// <param name="type">the type to explode</param> /// <returns>the typeinfo for this type (with the explosion)</returns> private TypeInfo ExplodeType(md.TypeUsage type) { if (TypeUtils.IsStructuredType(type)) { TypeInfo typeInfo = GetTypeInfo(type); ExplodeType(typeInfo); return(typeInfo); } if (TypeUtils.IsCollectionType(type)) { md.TypeUsage elementType = TypeHelpers.GetEdmType <md.CollectionType>(type).TypeUsage; ExplodeType(elementType); return(null); } return(null); }
/// <summary> /// SortOp handling /// /// First, "request" that for any sort key that is a structured type, we /// need all its properties. Then process any local definitions, and /// finally the relop input /// </summary> /// <param name="op"></param> /// <param name="n"></param> protected override void VisitSortOp(SortBaseOp op, Node n) { // foreach sort key, every single bit of the Var is needed foreach (InternalTrees.SortKey sk in op.Keys) { if (TypeUtils.IsStructuredType(sk.Var.Type)) { AddPropertyRefs(sk.Var, PropertyRefList.All); } } // if the sort has any local definitions, process those first if (n.HasChild1) { VisitNode(n.Child1); } // then process the relop input VisitNode(n.Child0); }
/// <summary> /// Create a TypeInfo (if necessary) for the type, and add it to the TypeInfo map /// </summary> /// <param name="type">the type to process</param> private void CreateTypeInfoForType(md.TypeUsage type) { // // peel off all collection wrappers // while (TypeUtils.IsCollectionType(type)) { type = TypeHelpers.GetEdmType <md.CollectionType>(type).TypeUsage; } // Only add "structured" types if (TypeUtils.IsStructuredType(type)) { // check for discriminator map... ExplicitDiscriminatorMap discriminatorMap; TryGetDiscriminatorMap(type.EdmType, out discriminatorMap); CreateTypeInfoForStructuredType(type, discriminatorMap); } }
/// <summary> /// Common handler for RelPropertyOp and PropertyOp. /// Simply pushes down the desired set of properties to the child /// </summary> /// <param name="op">the *propertyOp</param> /// <param name="n">node tree corresponding to the Op</param> /// <param name="propertyRef">the property reference</param> private void VisitPropertyOp(Op op, Node n, PropertyRef propertyRef) { PropertyRefList cdProps = new PropertyRefList(); if (!TypeUtils.IsStructuredType(op.Type)) { cdProps.Add(propertyRef); } else { // Get the list of properties my parent expects from me. PropertyRefList pdProps = GetPropertyRefList(n); // Ask my child (which is really my container type) for each of these // properties // If I've been asked for all my properties, then get the // corresponding flat list of properties from my children. // For now, however, simply ask for all properties in this case // What we really need to do is to get the "flattened" list of // properties from the input, and prepend each of these with // our property name. We don't have that info available, so // I'm taking the easier route. if (pdProps.AllProperties) { cdProps = pdProps; } else { foreach (PropertyRef p in pdProps.Properties) { cdProps.Add(p.CreateNestedPropertyRef(propertyRef)); } } } // push down my expectations AddPropertyRefs(n.Child0, cdProps); VisitChildren(n); }
/// <summary> /// Add a new entry to the map. If an entry already exists, then this function /// simply returns the existing entry. Otherwise a new entry is created. If /// the type has a supertype, then we ensure that the supertype also exists in /// the map, and we add our info to the supertype's list of subtypes /// </summary> /// <param name="type">New type to add</param> /// <param name="discriminatorMap">type discriminator map</param> /// <returns>The TypeInfo for this type</returns> private TypeInfo CreateTypeInfoForStructuredType(md.TypeUsage type, ExplicitDiscriminatorMap discriminatorMap) { TypeInfo typeInfo; PlanCompiler.Assert(TypeUtils.IsStructuredType(type), "expected structured type. Found " + type); // Return existing entry, if one is available typeInfo = GetTypeInfo(type); if (typeInfo != null) { return(typeInfo); } // Ensure that my supertype has been added to the map. TypeInfo superTypeInfo = null; md.RefType refType; if (type.EdmType.BaseType != null) { superTypeInfo = CreateTypeInfoForStructuredType(md.TypeUsage.Create(type.EdmType.BaseType), discriminatorMap); } // // Handle Ref types also in a similar fashion // else if (TypeHelpers.TryGetEdmType <md.RefType>(type, out refType)) { md.EntityType entityType = refType.ElementType as md.EntityType; if (entityType != null && entityType.BaseType != null) { md.TypeUsage baseRefType = TypeHelpers.CreateReferenceTypeUsage(entityType.BaseType as md.EntityType); superTypeInfo = CreateTypeInfoForStructuredType(baseRefType, discriminatorMap); } } // // Add the types of my properties to the TypeInfo map // foreach (md.EdmMember m in TypeHelpers.GetDeclaredStructuralMembers(type)) { CreateTypeInfoForType(m.TypeUsage); } // // Get the types of the rel properties also // { md.EntityTypeBase entityType; if (TypeHelpers.TryGetEdmType <md.EntityTypeBase>(type, out entityType)) { foreach (RelProperty p in m_relPropertyHelper.GetDeclaredOnlyRelProperties(entityType)) { CreateTypeInfoForType(p.ToEnd.TypeUsage); } } } // Now add myself to the map typeInfo = TypeInfo.Create(type, superTypeInfo, discriminatorMap); m_typeInfoMap.Add(type, typeInfo); return(typeInfo); }