/// <summary> /// Given the <paramref name="member"/> and one of its <paramref name="possibleType"/>s, determine the attributes that are relevant /// for this <paramref name="possibleType"/> and return a <see cref="MemberPath"/> signature corresponding to the <paramref name="possibleType"/> and the attributes. /// If <paramref name="needKeysOnly"/>=true, collect the key fields only. /// </summary> /// <param name="possibleType">the <paramref name="member"/>'s type or one of its subtypes</param> private static void GatherSignatureFromTypeStructuralMembers(MemberProjectionIndex index, EdmItemCollection edmItemCollection, MemberPath member, StructuralType possibleType, bool needKeysOnly) { // For each child member of this type, collect all the relevant scalar fields foreach (EdmMember structuralMember in Helper.GetAllStructuralMembers(possibleType)) { if (MetadataHelper.IsNonRefSimpleMember(structuralMember)) { if (!needKeysOnly || MetadataHelper.IsPartOfEntityTypeKey(structuralMember)) { MemberPath nonStructuredMember = new MemberPath(member, structuralMember); // Note: scalarMember's parent has already been added to the projectedSlotMap index.CreateIndex(nonStructuredMember); } } else { Debug.Assert(structuralMember.TypeUsage.EdmType is ComplexType || structuralMember.TypeUsage.EdmType is RefType, // for association ends "Only non-scalars expected - complex types, association ends"); MemberPath structuredMember = new MemberPath(member, structuralMember); GatherPartialSignature(index, edmItemCollection, structuredMember, // Only keys are required for entities referenced by association ends of an association. needKeysOnly || Helper.IsAssociationEndMember(structuralMember)); } } }
internal static void GetRequiredSlots(DomainBoolExpr expression, MemberProjectionIndex projectedSlotMap, bool[] requiredSlots) { RequiredSlotsVisitor visitor = new RequiredSlotsVisitor(projectedSlotMap, requiredSlots); expression.Accept <DomainBoolExpr>(visitor); }
/// <summary> /// Starting at the <paramref name="member"/>, recursively generates <see cref="MemberPath"/>s for the fields embedded in it. /// </summary> /// <param name="member">corresponds to a value of an Entity or Complex or Association type</param> /// <param name="needKeysOnly">indicates whether we need to only collect members that are keys</param> private static void GatherPartialSignature(MemberProjectionIndex index, EdmItemCollection edmItemCollection, MemberPath member, bool needKeysOnly) { EdmType memberType = member.EdmType; ComplexType complexTypemember = memberType as ComplexType; Debug.Assert(complexTypemember != null || memberType is EntityType || // for entity sets memberType is AssociationType || // For association sets memberType is RefType, // for association ends "GatherPartialSignature can be called only for complex types, entity sets, association ends"); if (memberType is ComplexType && needKeysOnly) { // Check if the complex type needs to be traversed or not. If not, just return // from here. Else we need to continue to the code below. Right now, we do not // allow keys inside complex types return; } // Make sure that this member is in the slot map before any of its embedded objects. index.CreateIndex(member); // Consider each possible type value -- each type value conributes to a tuple in the result. // For that possible type, add all the type members into the signature. foreach (EdmType possibleType in MetadataHelper.GetTypeAndSubtypesOf(memberType, edmItemCollection, false /*includeAbstractTypes*/)) { StructuralType possibleStructuralType = possibleType as StructuralType; Debug.Assert(possibleStructuralType != null, "Non-structural subtype?"); GatherSignatureFromTypeStructuralMembers(index, edmItemCollection, member, possibleStructuralType, needKeysOnly); } }
/// <summary> /// Recursively generates <see cref="MemberPath"/>s for the members of the types stored in the <paramref name="extent"/>. /// </summary> internal static MemberProjectionIndex Create(EntitySetBase extent, EdmItemCollection edmItemCollection) { // We generate the indices for the projected slots as we traverse the metadata. MemberProjectionIndex index = new MemberProjectionIndex(); GatherPartialSignature(index, edmItemCollection, new MemberPath(extent), false); // need not only keys return index; }
internal override void GetRequiredSlots(MemberProjectionIndex projectedSlotMap, bool[] requiredSlots) { // The slot corresponding to from1, etc int numBoolSlots = requiredSlots.Length - projectedSlotMap.Count; int slotNum = projectedSlotMap.BoolIndexToSlot(m_index, numBoolSlots); requiredSlots[slotNum] = true; }
/// <summary> /// See <see cref="BoolLiteral.GetRequiredSlots"/>. /// </summary> internal override void GetRequiredSlots(MemberProjectionIndex projectedSlotMap, bool[] requiredSlots) { // Simply get the slot for the variable var in "var in values" MemberPath member = RestrictedMemberSlot.MemberPath; int slotNum = projectedSlotMap.IndexOf(member); requiredSlots[slotNum] = true; }
/// <summary> /// Recursively generates <see cref="MemberPath"/>s for the members of the types stored in the <paramref name="extent"/>. /// </summary> internal static MemberProjectionIndex Create(EntitySetBase extent, EdmItemCollection edmItemCollection) { // We generate the indices for the projected slots as we traverse the metadata. MemberProjectionIndex index = new MemberProjectionIndex(); GatherPartialSignature(index, edmItemCollection, new MemberPath(extent), false); // need not only keys return(index); }
// effects: Creates a view generator object that can be used to generate views // based on usedCells (projectedSlotMap are useful for deciphering the fields) internal BasicViewGenerator(MemberProjectionIndex projectedSlotMap, List<LeftCellWrapper> usedCells, FragmentQuery activeDomain, ViewgenContext context, MemberDomainMap domainMap, ErrorLog errorLog, ConfigViewGenerator config) { Debug.Assert(usedCells.Count > 0, "No used cells"); m_projectedSlotMap = projectedSlotMap; m_usedCells = usedCells; m_viewgenContext = context; m_activeDomain = activeDomain; m_errorLog = errorLog; m_config = config; m_domainMap = domainMap; }
internal MemberMaps(ViewTarget viewTarget, MemberProjectionIndex projectedSlotMap, MemberDomainMap queryDomainMap, MemberDomainMap updateDomainMap) { m_projectedSlotMap = projectedSlotMap; m_queryDomainMap = queryDomainMap; m_updateDomainMap = updateDomainMap; Debug.Assert(m_queryDomainMap != null); Debug.Assert(m_updateDomainMap != null); Debug.Assert(m_projectedSlotMap != null); m_viewTarget = viewTarget; }
/// <summary> /// Given the generated <paramref name="view"/>, the <paramref name="caseStatements"/> for the multiconstant fields, /// the <paramref name="projectedSlotMap"/> that maps different paths of the entityset (for which the view is being generated) to slot indexes in the view, /// creates an object that is capable of generating the Cql for <paramref name="view"/>. /// </summary> internal CqlGenerator(CellTreeNode view, Dictionary<MemberPath, CaseStatement> caseStatements, CqlIdentifiers identifiers, MemberProjectionIndex projectedSlotMap, int numCellsInView, BoolExpression topLevelWhereClause, StorageMappingItemCollection mappingItemCollection) { m_view = view; m_caseStatements = caseStatements; m_projectedSlotMap = projectedSlotMap; m_numBools = numCellsInView; // We have that many booleans m_topLevelWhereClause = topLevelWhereClause; m_identifiers = identifiers; m_mappingItemCollection = mappingItemCollection; }
// requires: projectedSlotMap which contains a mapping of the fields // for "this" to integers // effects: Align the fields of this cell query using the // projectedSlotMap and generates a new query into newMainQuery // Based on the re-aligned fields in this, re-aligns the // corresponding fields in otherQuery as well and modifies // newOtherQuery to contain it // Example: // input: Proj[A,B,"5"] = Proj[F,"7",G] // Proj[C,B] = Proj[H,I] // projectedSlotMap: A -> 0, B -> 1, C -> 2 // output: Proj[A,B,null] = Proj[F,"7",null] // Proj[null,B,C] = Proj[null,I,H] internal void CreateFieldAlignedCellQueries(CellQuery otherQuery, MemberProjectionIndex projectedSlotMap, out CellQuery newMainQuery, out CellQuery newOtherQuery) { // mainSlots and otherSlots hold the new slots for two queries int numAlignedSlots = projectedSlotMap.Count; ProjectedSlot[] mainSlots = new ProjectedSlot[numAlignedSlots]; ProjectedSlot[] otherSlots = new ProjectedSlot[numAlignedSlots]; // Go through the slots for this query and find the new slot for them for (int i = 0; i < m_projectedSlots.Length; i++) { MemberProjectedSlot slot = m_projectedSlots[i] as MemberProjectedSlot; Debug.Assert(slot != null, "All slots during cell normalization must field slots"); // Get the the ith slot's variable and then get the // new slot number from the field map int newSlotNum = projectedSlotMap.IndexOf(slot.MemberPath); Debug.Assert(newSlotNum >= 0, "Field projected but not in projectedSlotMap"); mainSlots[newSlotNum] = m_projectedSlots[i]; otherSlots[newSlotNum] = otherQuery.m_projectedSlots[i]; // We ignore constants -- note that this is not the // isHighpriority or discriminator case. An example of this // is when (say) Address does not have zip but USAddress // does. Then the constraint looks like Pi_NULL, A, B(E) = // Pi_x, y, z(S) // We don't care about this null in the view generation of // the left side. Note that this could happen in inheritance // or in cases when say the S side has 20 fields but the C // side has only 3 - the other 17 are null or default. // NOTE: We allow such constants only on the C side and not // ont the S side. Otherwise, we can have a situation Pi_A, // B, C(E) = Pi_5, y, z(S) Then someone can set A to 7 and we // will not roundtrip. We check for this in validation } // Make the new cell queries with the new slots newMainQuery = new CellQuery(this, mainSlots); newOtherQuery = new CellQuery(otherQuery, otherSlots); }
internal override void GetRequiredSlots(MemberProjectionIndex projectedSlotMap, bool[] requiredSlots) { throw new NotImplementedException(); }
// effects: Given a boolean expression, modifies requiredSlots // to indicate which slots are required to generate the expression // projectedSlotMap indicates a mapping from member paths to slot // numbers (that need to be checked off in requiredSlots) internal virtual void GetRequiredSlots(MemberProjectionIndex projectedSlotMap, bool[] requiredSlots) { RequiredSlotsVisitor.GetRequiredSlots(m_tree, projectedSlotMap, requiredSlots); }
/// <summary> /// See <see cref="BoolExpression.GetRequiredSlots"/>. /// </summary> /// <param name="projectedSlotMap"></param> /// <param name="requiredSlots"></param> internal abstract void GetRequiredSlots(MemberProjectionIndex projectedSlotMap, bool[] requiredSlots);
private RequiredSlotsVisitor(MemberProjectionIndex projectedSlotMap, bool[] requiredSlots) { m_projectedSlotMap = projectedSlotMap; m_requiredSlots = requiredSlots; }
// requires: projectedSlotMap which contains a mapping of the fields // for "this" to integers // effects: Align the fields of this cell query using the // projectedSlotMap and generates a new query into newMainQuery // Based on the re-aligned fields in this, re-aligns the // corresponding fields in otherQuery as well and modifies // newOtherQuery to contain it // Example: // input: Proj[A,B,"5"] = Proj[F,"7",G] // Proj[C,B] = Proj[H,I] // projectedSlotMap: A -> 0, B -> 1, C -> 2 // output: Proj[A,B,null] = Proj[F,"7",null] // Proj[null,B,C] = Proj[null,I,H] internal void CreateFieldAlignedCellQueries( CellQuery otherQuery, MemberProjectionIndex projectedSlotMap, out CellQuery newMainQuery, out CellQuery newOtherQuery) { // mainSlots and otherSlots hold the new slots for two queries var numAlignedSlots = projectedSlotMap.Count; var mainSlots = new ProjectedSlot[numAlignedSlots]; var otherSlots = new ProjectedSlot[numAlignedSlots]; // Go through the slots for this query and find the new slot for them for (var i = 0; i < m_projectedSlots.Length; i++) { var slot = m_projectedSlots[i] as MemberProjectedSlot; Debug.Assert(slot != null, "All slots during cell normalization must field slots"); // Get the the ith slot's variable and then get the // new slot number from the field map var newSlotNum = projectedSlotMap.IndexOf(slot.MemberPath); Debug.Assert(newSlotNum >= 0, "Field projected but not in projectedSlotMap"); mainSlots[newSlotNum] = m_projectedSlots[i]; otherSlots[newSlotNum] = otherQuery.m_projectedSlots[i]; // We ignore constants -- note that this is not the // isHighpriority or discriminator case. An example of this // is when (say) Address does not have zip but USAddress // does. Then the constraint looks like Pi_NULL, A, B(E) = // Pi_x, y, z(S) // We don't care about this null in the view generation of // the left side. Note that this could happen in inheritance // or in cases when say the S side has 20 fields but the C // side has only 3 - the other 17 are null or default. // NOTE: We allow such constants only on the C side and not // ont the S side. Otherwise, we can have a situation Pi_A, // B, C(E) = Pi_5, y, z(S) Then someone can set A to 7 and we // will not roundtrip. We check for this in validation } // Make the new cell queries with the new slots newMainQuery = new CellQuery(this, mainSlots); newOtherQuery = new CellQuery(otherQuery, otherSlots); }
// effects: Align the fields of each cell in mapping using projectedSlotMap that has a mapping // for each member of this extent to the slot number of that member in the projected slots // example: // input: Proj[A,B,"5"] = Proj[F,"7",G] // Proj[C,B] = Proj[H,I] // output: m_projectedSlotMap: A -> 0, B -> 1, C -> 2 // Proj[A,B,null] = Proj[F,"7",null] // Proj[null,B,C] = Proj[null,I,H] private static List<Cell> AlignFields(IEnumerable<Cell> cells, MemberProjectionIndex projectedSlotMap, ViewTarget viewTarget) { List<Cell> outputCells = new List<Cell>(); // Determine the aligned field for each cell // The new cells have ProjectedSlotMap.Count number of fields foreach (Cell cell in cells) { // If isQueryView is true, we need to consider the C side of // the cells; otherwise, we look at the S side. Note that we // CANNOT use cell.LeftQuery since that is determined by // cell's isQueryView // The query for which we are constructing the extent CellQuery mainQuery = cell.GetLeftQuery(viewTarget); CellQuery otherQuery = cell.GetRightQuery(viewTarget); CellQuery newMainQuery; CellQuery newOtherQuery; // Create both queries where the projected slot map is used // to determine the order of the fields of the mainquery (of // course, the otherQuery's fields are aligned automatically) mainQuery.CreateFieldAlignedCellQueries(otherQuery, projectedSlotMap, out newMainQuery, out newOtherQuery); Cell outputCell = viewTarget == ViewTarget.QueryView ? Cell.CreateCS(newMainQuery, newOtherQuery, cell.CellLabel, cell.CellNumber) : Cell.CreateCS(newOtherQuery, newMainQuery, cell.CellLabel, cell.CellNumber); outputCells.Add(outputCell); } return outputCells; }