private void CheckImplication( SchemaConstraints <ViewKeyConstraint> cViewConstraints, SchemaConstraints <ViewKeyConstraint> sViewConstraints) { this.CheckImplicationKeyConstraints(cViewConstraints, sViewConstraints); KeyToListMap <CellGroupValidator.ExtentPair, ViewKeyConstraint> keyToListMap = new KeyToListMap <CellGroupValidator.ExtentPair, ViewKeyConstraint>((IEqualityComparer <CellGroupValidator.ExtentPair>)EqualityComparer <CellGroupValidator.ExtentPair> .Default); foreach (ViewKeyConstraint keyConstraint in cViewConstraints.KeyConstraints) { CellGroupValidator.ExtentPair key = new CellGroupValidator.ExtentPair(keyConstraint.Cell.CQuery.Extent, keyConstraint.Cell.SQuery.Extent); keyToListMap.Add(key, keyConstraint); } foreach (CellGroupValidator.ExtentPair key in keyToListMap.Keys) { ReadOnlyCollection <ViewKeyConstraint> readOnlyCollection = keyToListMap.ListForKey(key); bool flag = false; foreach (ViewKeyConstraint second in readOnlyCollection) { foreach (ViewKeyConstraint keyConstraint in sViewConstraints.KeyConstraints) { if (keyConstraint.Implies(second)) { flag = true; break; } } } if (!flag) { this.m_errorLog.AddEntry(ViewKeyConstraint.GetErrorRecord((IEnumerable <ViewKeyConstraint>)readOnlyCollection)); } } }
internal List <Set <Cell> > GroupRelatedCells() { UndirectedGraph <EntitySetBase> undirectedGraph = new UndirectedGraph <EntitySetBase>((IEqualityComparer <EntitySetBase>)EqualityComparer <EntitySetBase> .Default); Dictionary <EntitySetBase, Set <Cell> > extentToCell = new Dictionary <EntitySetBase, Set <Cell> >((IEqualityComparer <EntitySetBase>)EqualityComparer <EntitySetBase> .Default); foreach (Cell cell in this.m_cells) { EntitySetBase[] entitySetBaseArray = new EntitySetBase[2] { cell.CQuery.Extent, cell.SQuery.Extent }; foreach (EntitySetBase index in entitySetBaseArray) { Set <Cell> set; if (!extentToCell.TryGetValue(index, out set)) { extentToCell[index] = set = new Set <Cell>(); } set.Add(cell); undirectedGraph.AddVertex(index); } undirectedGraph.AddEdge(cell.CQuery.Extent, cell.SQuery.Extent); AssociationSet extent = cell.CQuery.Extent as AssociationSet; if (extent != null) { foreach (AssociationSetEnd associationSetEnd in extent.AssociationSetEnds) { undirectedGraph.AddEdge((EntitySetBase)associationSetEnd.EntitySet, (EntitySetBase)extent); } } } foreach (ForeignConstraint foreignKeyConstraint in this.m_foreignKeyConstraints) { undirectedGraph.AddEdge((EntitySetBase)foreignKeyConstraint.ChildTable, (EntitySetBase)foreignKeyConstraint.ParentTable); } KeyToListMap <int, EntitySetBase> connectedComponents = undirectedGraph.GenerateConnectedComponents(); List <Set <Cell> > setList = new List <Set <Cell> >(); foreach (int key in connectedComponents.Keys) { IEnumerable <Set <Cell> > sets = connectedComponents.ListForKey(key).Select <EntitySetBase, Set <Cell> >((Func <EntitySetBase, Set <Cell> >)(e => extentToCell[e])); Set <Cell> set1 = new Set <Cell>(); foreach (Set <Cell> set2 in sets) { set1.AddRange((IEnumerable <Cell>)set2); } setList.Add(set1); } return(setList); }
// effects: Given a graph of cell groups, returns a list of cellgroup // such that each cellgroup contains all the cells that are in the // same connected component private static List <CellGroup> GenerateConnectedComponents(UndirectedGraph <Cell> graph) { KeyToListMap <int, Cell> groupMap = graph.GenerateConnectedComponents(); // Run through the list of groups and generate the merged groups List <CellGroup> result = new List <CellGroup>(); foreach (int setNum in groupMap.Keys) { ReadOnlyCollection <Cell> cellsInComponent = groupMap.ListForKey(setNum); CellGroup component = new CellGroup(cellsInComponent); result.Add(component); } return(result); }
// effects: A restrictive version of GroupLeafChildrenByExtent -- // only for LASJ and LOJ nodes (works for LOJ only when A LOJ B LOJ C // s.t., B and C are subsets of A -- in our case that is how LOJs are constructed private static List <CellTreeNode> GroupNonAssociativeLeafChildren(List <CellTreeNode> nodes) { // Keep track of leaf cells for each extent ignoring the 0th child var extentMap = new KeyToListMap <EntitySetBase, CellTreeNode>(EqualityComparer <EntitySetBase> .Default); var newNodes = new List <CellTreeNode>(); var nonLeafNodes = new List <CellTreeNode>(); // Add the 0th child newNodes.Add(nodes[0]); for (var i = 1; i < nodes.Count; i++) { var node = nodes[i]; var leafNode = node as LeafCellTreeNode; // All non-leaf nodes are added to the result now // leaf nodes are added outside the loop if (leafNode != null) { extentMap.Add(leafNode.LeftCellWrapper.RightCellQuery.Extent, leafNode); } else { nonLeafNodes.Add(node); } } // Go through the map and add the leaf children // If a group of nodes exists for the 0th node's extent -- place // that group first var firstNode = nodes[0] as LeafCellTreeNode; if (firstNode != null) { var firstExtent = firstNode.LeftCellWrapper.RightCellQuery.Extent; if (extentMap.ContainsKey(firstExtent)) { newNodes.AddRange(extentMap.ListForKey(firstExtent)); // Remove this set from the map extentMap.RemoveKey(firstExtent); } } newNodes.AddRange(extentMap.AllValues); newNodes.AddRange(nonLeafNodes); return(newNodes); }
// effects: Checks if all sViewConstraints are implied by the // constraints in cViewConstraints. If some S-level constraints are // not implied, adds errors/warnings to m_errorLog private void CheckImplication(ViewSchemaConstraints cViewConstraints, ViewSchemaConstraints sViewConstraints) { // Check key constraints // i.e., if S has a key <k1, k2>, C must have a key that is a subset of this CheckImplicationKeyConstraints(cViewConstraints, sViewConstraints); // For updates, we need to ensure the following: for every // extent E, table T pair, some key of E is implied by T's key // Get all key constraints for each extent and each table var extentPairConstraints = new KeyToListMap <ExtentPair, ViewKeyConstraint>(EqualityComparer <ExtentPair> .Default); foreach (var cKeyConstraint in cViewConstraints.KeyConstraints) { var pair = new ExtentPair(cKeyConstraint.Cell.CQuery.Extent, cKeyConstraint.Cell.SQuery.Extent); extentPairConstraints.Add(pair, cKeyConstraint); } // Now check that we guarantee at least one constraint per // extent/table pair foreach (var extentPair in extentPairConstraints.Keys) { var cKeyConstraints = extentPairConstraints.ListForKey(extentPair); var sImpliesSomeC = false; // Go through all key constraints for the extent/table pair, and find one that S implies foreach (var cKeyConstraint in cKeyConstraints) { foreach (var sKeyConstraint in sViewConstraints.KeyConstraints) { if (sKeyConstraint.Implies(cKeyConstraint)) { sImpliesSomeC = true; break; // The implication holds - so no problem } } } if (sImpliesSomeC == false) { // Indicate that at least one key must be ensured on the S-side m_errorLog.AddEntry(ViewKeyConstraint.GetErrorRecord(cKeyConstraints)); } } }
internal ErrorLog.Record CheckForDuplicateFields(CellQuery cQuery, Cell sourceCell) { KeyToListMap <MemberProjectedSlot, int> keyToListMap = new KeyToListMap <MemberProjectedSlot, int>((IEqualityComparer <MemberProjectedSlot>)ProjectedSlot.EqualityComparer); for (int index = 0; index < this.m_projectedSlots.Length; ++index) { MemberProjectedSlot projectedSlot = this.m_projectedSlots[index] as MemberProjectedSlot; keyToListMap.Add(projectedSlot, index); } StringBuilder stringBuilder1 = (StringBuilder)null; bool flag = false; foreach (MemberProjectedSlot key in keyToListMap.Keys) { ReadOnlyCollection <int> cSideSlotIndexes = keyToListMap.ListForKey(key); if (cSideSlotIndexes.Count > 1 && !cQuery.AreSlotsEquivalentViaRefConstraints(cSideSlotIndexes)) { flag = true; if (stringBuilder1 == null) { stringBuilder1 = new StringBuilder(Strings.ViewGen_Duplicate_CProperties((object)this.Extent.Name)); stringBuilder1.AppendLine(); } StringBuilder stringBuilder2 = new StringBuilder(); for (int index1 = 0; index1 < cSideSlotIndexes.Count; ++index1) { int index2 = cSideSlotIndexes[index1]; if (index1 != 0) { stringBuilder2.Append(", "); } MemberProjectedSlot projectedSlot = (MemberProjectedSlot)cQuery.m_projectedSlots[index2]; stringBuilder2.Append(projectedSlot.ToUserString()); } stringBuilder1.AppendLine(Strings.ViewGen_Duplicate_CProperties_IsMapped((object)key.ToUserString(), (object)stringBuilder2.ToString())); } } if (!flag) { return((ErrorLog.Record)null); } return(new ErrorLog.Record(ViewGenErrorCode.DuplicateCPropertiesMapped, stringBuilder1.ToString(), sourceCell, string.Empty)); }
// requires: The tree rooted at cellTreeNode is an FOJ tree of // LeafCellTreeNodes only, i.e., there is an FOJ node with the // children being LeafCellTreeNodes // // effects: Given a tree rooted at rootNode, ensures that cells // of the same right extent are placed in their own subtree below // cellTreeNode. That is, if there are 3 cells of extent A and 2 of // extent B (i.e., 5 cells with an FOJ on it), the resulting tree has // an FOJ node with two children -- FOJ nodes. These FOJ nodes have 2 // and 3 children internal CellTreeNode GroupByRightExtent(CellTreeNode rootNode) { // A dictionary that maps an extent to the nodes are from that extent // We want a ref comparer here var extentMap = new KeyToListMap <EntitySetBase, LeafCellTreeNode>(EqualityComparer <EntitySetBase> .Default); // CR_Meek_Low: method can be simplified (Map<Extent, OpCellTreeNode>, populate as you go) // (becomes self-documenting) // For each leaf child, find the extent of the child and place it // in extentMap foreach (LeafCellTreeNode childNode in rootNode.Children) { // A cell may contain P, P.PA -- we return P // CHANGE_ADYA_FEATURE_COMPOSITION Need to fix for composition!! var extent = childNode.LeftCellWrapper.RightCellQuery.Extent; // relation or extent to group by Debug.Assert(extent != null, "Each cell must have a right extent"); // Add the childNode as a child of the FOJ tree for "extent" extentMap.Add(extent, childNode); } // Now go through the extent map and create FOJ nodes for each extent // Place the nodes for that extent in the newly-created FOJ subtree // Also add the op node for every node as a child of the final result var result = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.FOJ); foreach (var extent in extentMap.Keys) { var extentFojNode = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.FOJ); foreach (var childNode in extentMap.ListForKey(extent)) { extentFojNode.Add(childNode); } result.Add(extentFojNode); } // We call Flatten to remove any unnecessary nestings // where an OpNode has only 1 child. return(result.Flatten()); }
internal CellTreeNode GroupByRightExtent(CellTreeNode rootNode) { KeyToListMap <EntitySetBase, LeafCellTreeNode> keyToListMap = new KeyToListMap <EntitySetBase, LeafCellTreeNode>((IEqualityComparer <EntitySetBase>)EqualityComparer <EntitySetBase> .Default); foreach (LeafCellTreeNode child in rootNode.Children) { EntitySetBase extent = child.LeftCellWrapper.RightCellQuery.Extent; keyToListMap.Add(extent, child); } OpCellTreeNode opCellTreeNode1 = new OpCellTreeNode(this.m_viewgenContext, CellTreeOpType.FOJ); foreach (EntitySetBase key in keyToListMap.Keys) { OpCellTreeNode opCellTreeNode2 = new OpCellTreeNode(this.m_viewgenContext, CellTreeOpType.FOJ); foreach (LeafCellTreeNode leafCellTreeNode in keyToListMap.ListForKey(key)) { opCellTreeNode2.Add((CellTreeNode)leafCellTreeNode); } opCellTreeNode1.Add((CellTreeNode)opCellTreeNode2); } return(opCellTreeNode1.Flatten()); }
private static List <CellTreeNode> GroupNonAssociativeLeafChildren( List <CellTreeNode> nodes) { KeyToListMap <EntitySetBase, CellTreeNode> keyToListMap = new KeyToListMap <EntitySetBase, CellTreeNode>((IEqualityComparer <EntitySetBase>)EqualityComparer <EntitySetBase> .Default); List <CellTreeNode> cellTreeNodeList1 = new List <CellTreeNode>(); List <CellTreeNode> cellTreeNodeList2 = new List <CellTreeNode>(); cellTreeNodeList1.Add(nodes[0]); for (int index = 1; index < nodes.Count; ++index) { CellTreeNode node = nodes[index]; LeafCellTreeNode leafCellTreeNode = node as LeafCellTreeNode; if (leafCellTreeNode != null) { keyToListMap.Add(leafCellTreeNode.LeftCellWrapper.RightCellQuery.Extent, (CellTreeNode)leafCellTreeNode); } else { cellTreeNodeList2.Add(node); } } LeafCellTreeNode node1 = nodes[0] as LeafCellTreeNode; if (node1 != null) { EntitySetBase extent = node1.LeftCellWrapper.RightCellQuery.Extent; if (keyToListMap.ContainsKey(extent)) { cellTreeNodeList1.AddRange((IEnumerable <CellTreeNode>)keyToListMap.ListForKey(extent)); keyToListMap.RemoveKey(extent); } } cellTreeNodeList1.AddRange(keyToListMap.AllValues); cellTreeNodeList1.AddRange((IEnumerable <CellTreeNode>)cellTreeNodeList2); return(cellTreeNodeList1); }
// requires: All slots in this are join tree slots // This method is called for an S-side query // cQuery is the corresponding C-side query in the cell // sourceCell is the original cell for "this" and cQuery // effects: Checks if any of the columns in "this" are mapped to multiple properties in cQuery. If so, // returns an error record about the duplicated slots internal ErrorLog.Record CheckForDuplicateFields(CellQuery cQuery, Cell sourceCell) { // slotMap stores the slots on the S-side and the // C-side properties that it maps to var slotMap = new KeyToListMap <MemberProjectedSlot, int>(ProjectedSlot.EqualityComparer); // Note that this does work for self-association. In the manager // employee example, ManagerId and EmployeeId from the SEmployee // table map to the two ends -- Manager.ManagerId and // Employee.EmployeeId in the C Space for (var i = 0; i < m_projectedSlots.Length; i++) { var projectedSlot = m_projectedSlots[i]; var slot = projectedSlot as MemberProjectedSlot; Debug.Assert(slot != null, "All slots for this method must be JoinTreeSlots"); slotMap.Add(slot, i); } StringBuilder builder = null; // Now determine the entries that have more than one integer per slot var isErrorSituation = false; foreach (var slot in slotMap.Keys) { var indexes = slotMap.ListForKey(slot); Debug.Assert(indexes.Count >= 1, "Each slot must have one index at least"); if (indexes.Count > 1 && cQuery.AreSlotsEquivalentViaRefConstraints(indexes) == false) { // The column is mapped to more than one property and it // failed the "association corresponds to referential // constraints" check isErrorSituation = true; if (builder == null) { builder = new StringBuilder(Strings.ViewGen_Duplicate_CProperties(Extent.Name)); builder.AppendLine(); } var tmpBuilder = new StringBuilder(); for (var i = 0; i < indexes.Count; i++) { var index = indexes[i]; if (i != 0) { tmpBuilder.Append(", "); } // The slot must be a JoinTreeSlot. If it isn't it is an internal error var cSlot = (MemberProjectedSlot)cQuery.m_projectedSlots[index]; tmpBuilder.Append(cSlot.ToUserString()); } builder.AppendLine(Strings.ViewGen_Duplicate_CProperties_IsMapped(slot.ToUserString(), tmpBuilder.ToString())); } } if (false == isErrorSituation) { return(null); } var record = new ErrorLog.Record(ViewGenErrorCode.DuplicateCPropertiesMapped, builder.ToString(), sourceCell, String.Empty); return(record); }
// requires: The tree rooted at cellTreeNode is an FOJ tree of // LeafCellTreeNodes only, i.e., there is an FOJ node with the // children being LeafCellTreeNodes // // effects: Given a tree rooted at rootNode, ensures that cells // of the same right extent are placed in their own subtree below // cellTreeNode. That is, if there are 3 cells of extent A and 2 of // extent B (i.e., 5 cells with an FOJ on it), the resulting tree has // an FOJ node with two children -- FOJ nodes. These FOJ nodes have 2 // and 3 children internal CellTreeNode GroupByRightExtent(CellTreeNode rootNode) { // A dictionary that maps an extent to the nodes are from that extent // We want a ref comparer here var extentMap = new KeyToListMap<EntitySetBase, LeafCellTreeNode>(EqualityComparer<EntitySetBase>.Default); // CR_Meek_Low: method can be simplified (Map<Extent, OpCellTreeNode>, populate as you go) // (becomes self-documenting) // For each leaf child, find the extent of the child and place it // in extentMap foreach (LeafCellTreeNode childNode in rootNode.Children) { // A cell may contain P, P.PA -- we return P // CHANGE_ADYA_FEATURE_COMPOSITION Need to fix for composition!! var extent = childNode.LeftCellWrapper.RightCellQuery.Extent; // relation or extent to group by Debug.Assert(extent != null, "Each cell must have a right extent"); // Add the childNode as a child of the FOJ tree for "extent" extentMap.Add(extent, childNode); } // Now go through the extent map and create FOJ nodes for each extent // Place the nodes for that extent in the newly-created FOJ subtree // Also add the op node for every node as a child of the final result var result = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.FOJ); foreach (var extent in extentMap.Keys) { var extentFojNode = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.FOJ); foreach (var childNode in extentMap.ListForKey(extent)) { extentFojNode.Add(childNode); } result.Add(extentFojNode); } // We call Flatten to remove any unnecessary nestings // where an OpNode has only 1 child. return result.Flatten(); }
// requires: All slots in this are join tree slots // This method is called for an S-side query // cQuery is the corresponding C-side query in the cell // sourceCell is the original cell for "this" and cQuery // effects: Checks if any of the columns in "this" are mapped to multiple properties in cQuery. If so, // returns an error record about the duplicated slots internal ErrorLog.Record CheckForDuplicateFields(CellQuery cQuery, Cell sourceCell) { // slotMap stores the slots on the S-side and the // C-side properties that it maps to var slotMap = new KeyToListMap<MemberProjectedSlot, int>(ProjectedSlot.EqualityComparer); // Note that this does work for self-association. In the manager // employee example, ManagerId and EmployeeId from the SEmployee // table map to the two ends -- Manager.ManagerId and // Employee.EmployeeId in the C Space for (var i = 0; i < m_projectedSlots.Length; i++) { var projectedSlot = m_projectedSlots[i]; var slot = projectedSlot as MemberProjectedSlot; Debug.Assert(slot != null, "All slots for this method must be JoinTreeSlots"); slotMap.Add(slot, i); } StringBuilder builder = null; // Now determine the entries that have more than one integer per slot var isErrorSituation = false; foreach (var slot in slotMap.Keys) { var indexes = slotMap.ListForKey(slot); Debug.Assert(indexes.Count >= 1, "Each slot must have one index at least"); if (indexes.Count > 1 && cQuery.AreSlotsEquivalentViaRefConstraints(indexes) == false) { // The column is mapped to more than one property and it // failed the "association corresponds to referential // constraints" check isErrorSituation = true; if (builder == null) { builder = new StringBuilder(Strings.ViewGen_Duplicate_CProperties(Extent.Name)); builder.AppendLine(); } var tmpBuilder = new StringBuilder(); for (var i = 0; i < indexes.Count; i++) { var index = indexes[i]; if (i != 0) { tmpBuilder.Append(", "); } // The slot must be a JoinTreeSlot. If it isn't it is an internal error var cSlot = (MemberProjectedSlot)cQuery.m_projectedSlots[index]; tmpBuilder.Append(cSlot.ToUserString()); } builder.AppendLine(Strings.ViewGen_Duplicate_CProperties_IsMapped(slot.ToUserString(), tmpBuilder.ToString())); } } if (false == isErrorSituation) { return null; } var record = new ErrorLog.Record(ViewGenErrorCode.DuplicateCPropertiesMapped, builder.ToString(), sourceCell, String.Empty); return record; }
// effects: Checks if all sViewConstraints are implied by the // constraints in cViewConstraints. If some S-level constraints are // not implied, adds errors/warnings to m_errorLog private void CheckImplication(ViewSchemaConstraints cViewConstraints, ViewSchemaConstraints sViewConstraints) { // Check key constraints // i.e., if S has a key <k1, k2>, C must have a key that is a subset of this CheckImplicationKeyConstraints(cViewConstraints, sViewConstraints); // For updates, we need to ensure the following: for every // extent E, table T pair, some key of E is implied by T's key // Get all key constraints for each extent and each table var extentPairConstraints = new KeyToListMap<ExtentPair, ViewKeyConstraint>(EqualityComparer<ExtentPair>.Default); foreach (var cKeyConstraint in cViewConstraints.KeyConstraints) { var pair = new ExtentPair(cKeyConstraint.Cell.CQuery.Extent, cKeyConstraint.Cell.SQuery.Extent); extentPairConstraints.Add(pair, cKeyConstraint); } // Now check that we guarantee at least one constraint per // extent/table pair foreach (var extentPair in extentPairConstraints.Keys) { var cKeyConstraints = extentPairConstraints.ListForKey(extentPair); var sImpliesSomeC = false; // Go through all key constraints for the extent/table pair, and find one that S implies foreach (var cKeyConstraint in cKeyConstraints) { foreach (var sKeyConstraint in sViewConstraints.KeyConstraints) { if (sKeyConstraint.Implies(cKeyConstraint)) { sImpliesSomeC = true; break; // The implication holds - so no problem } } } if (sImpliesSomeC == false) { // Indicate that at least one key must be ensured on the S-side m_errorLog.AddEntry(ViewKeyConstraint.GetErrorRecord(cKeyConstraints)); } } }
// effects: A restrictive version of GroupLeafChildrenByExtent -- // only for LASJ and LOJ nodes (works for LOJ only when A LOJ B LOJ C // s.t., B and C are subsets of A -- in our case that is how LOJs are constructed private static List<CellTreeNode> GroupNonAssociativeLeafChildren(List<CellTreeNode> nodes) { // Keep track of leaf cells for each extent ignoring the 0th child KeyToListMap<EntitySetBase, CellTreeNode> extentMap = new KeyToListMap<EntitySetBase, CellTreeNode>(EqualityComparer<EntitySetBase>.Default); List<CellTreeNode> newNodes = new List<CellTreeNode>(); List<CellTreeNode> nonLeafNodes = new List<CellTreeNode>(); // Add the 0th child newNodes.Add(nodes[0]); for (int i = 1; i < nodes.Count; i++) { CellTreeNode node = nodes[i]; LeafCellTreeNode leafNode = node as LeafCellTreeNode; // All non-leaf nodes are added to the result now // leaf nodes are added outside the loop if (leafNode != null) { extentMap.Add(leafNode.LeftCellWrapper.RightCellQuery.Extent, leafNode); } else { nonLeafNodes.Add(node); } } // Go through the map and add the leaf children // If a group of nodes exists for the 0th node's extent -- place // that group first LeafCellTreeNode firstNode = nodes[0] as LeafCellTreeNode; if (firstNode != null) { EntitySetBase firstExtent = firstNode.LeftCellWrapper.RightCellQuery.Extent; if (extentMap.ContainsKey(firstExtent)) { newNodes.AddRange(extentMap.ListForKey(firstExtent)); // Remove this set from the map extentMap.RemoveKey(firstExtent); } } newNodes.AddRange(extentMap.AllValues); newNodes.AddRange(nonLeafNodes); return newNodes; }