protected override void VisitScalarOpDefault(ScalarOp op, Node n) { using (new AutoString(this, op)) { string separator = string.Empty; foreach (Node chi in n.Children) { WriteString(separator); VisitNode(chi); separator = ","; } } }
protected override void VisitScalarOpDefault(ScalarOp op, Node n) { VisitDefault(n); Assert(op.Type != null, "ScalarOp {0} with no datatype!", op.OpType); if (op.OpType != OpType.Element && op.OpType != OpType.Exists && op.OpType != OpType.Collect) { foreach (Node chi in n.Children) { AssertScalarOp(chi.Op); } } }
/// <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; }
/// <summary> /// GetEntityKeyOp/GetRefKeyOp common handling /// /// In either case, get the "key" properties from the input entity/ref, and /// build up a record constructor from these values /// </summary> /// <param name="op">the GetRefKey/GetEntityKey op</param> /// <param name="n">current subtree</param> /// <returns>new expression subtree</returns> private Node FlattenGetKeyOp(ScalarOp op, Node n) { PlanCompiler.Assert(op.OpType == OpType.GetEntityRef || op.OpType == OpType.GetRefKey, "Expecting GetEntityRef or GetRefKey ops"); TypeInfo inputTypeInfo = m_typeInfo.GetTypeInfo(((ScalarOp)n.Child0.Op).Type); TypeInfo outputTypeInfo = m_typeInfo.GetTypeInfo(op.Type); // Visit the child - will flatten out the input ref/entity VisitChildren(n); // Get "key" properties (and the corresponding values) from the input List<md.EdmProperty> inputFieldTypes; List<Node> inputFieldValues; // Get the key properties for GetRefKey; get the Identity properties // for GetEntityRef if (op.OpType == OpType.GetRefKey) { GetPropertyValues(inputTypeInfo, OperationKind.GetKeys, n.Child0, false /* ignore missing props */, out inputFieldTypes, out inputFieldValues); } else { PlanCompiler.Assert(op.OpType == OpType.GetEntityRef, "Expected OpType.GetEntityRef: Found " + op.OpType); GetPropertyValues(inputTypeInfo, OperationKind.GetIdentity, n.Child0, false, out inputFieldTypes, out inputFieldValues); } if (outputTypeInfo.HasNullSentinelProperty && !inputTypeInfo.HasNullSentinelProperty) { // Add a null sentinel column, the input doesn't have one but the output requires it. inputFieldValues.Insert(0, CreateNullSentinelConstant()); } // create an appropriate record constructor List<md.EdmProperty> outputFieldTypes = new List<md.EdmProperty>(outputTypeInfo.FlattenedType.Properties); PlanCompiler.Assert(inputFieldValues.Count == outputFieldTypes.Count, "fieldTypes.Count mismatch?"); NewRecordOp rec = m_command.CreateNewRecordOp(outputTypeInfo.FlattenedTypeUsage, outputFieldTypes); Node newNode = m_command.CreateNode(rec, inputFieldValues); return newNode; }
/// <summary> /// Default handler for scalar Ops. Simply traverses the children, /// and also identifies any structured types along the way /// </summary> /// <param name="op">the ScalarOp</param> /// <param name="n">current subtree</param> /// <returns>the possibly modified node</returns> protected override Node VisitScalarOpDefault(ScalarOp op, Node n) { VisitChildren(n); // visit my children // keep track of referenced types AddTypeReference(op.Type); return n; }
protected override void VisitScalarOpDefault(ScalarOp op, Node n) { VisitDefault(n); Assert(op.Type != null, "ScalarOp {0} with no datatype!", op.OpType); if (op.OpType != OpType.Element && op.OpType != OpType.Exists && op.OpType != OpType.Collect) { foreach (var chi in n.Children) { AssertScalarOp(chi.Op); } } }
protected virtual void VisitScalarOpDefault(ScalarOp op, Node n) { VisitDefault(n); }