internal override bool VisitLeaf(LeafCellTreeNode node, bool dummy) { CellQuery rightCellQuery1 = this.m_wrapper.RightCellQuery; CellQuery rightCellQuery2 = node.LeftCellWrapper.RightCellQuery; List <MemberPath> memberPathList = new List <MemberPath>(); if (rightCellQuery1 != rightCellQuery2) { for (int slotNum = 0; slotNum < rightCellQuery1.NumProjectedSlots; ++slotNum) { MemberProjectedSlot memberProjectedSlot1 = rightCellQuery1.ProjectedSlotAt(slotNum) as MemberProjectedSlot; if (memberProjectedSlot1 != null) { MemberProjectedSlot memberProjectedSlot2 = rightCellQuery2.ProjectedSlotAt(slotNum) as MemberProjectedSlot; if (memberProjectedSlot2 != null) { MemberPath projectedSlot = this.m_viewgenContext.MemberMaps.ProjectedSlotMap[slotNum]; if (!projectedSlot.IsPartOfKey && !MemberPath.EqualityComparer.Equals(memberProjectedSlot1.MemberPath, memberProjectedSlot2.MemberPath)) { memberPathList.Add(projectedSlot); } } } } } if (memberPathList.Count > 0) { this.m_errorLog.AddEntry(new ErrorLog.Record(ViewGenErrorCode.NonKeyProjectedWithOverlappingPartitions, Strings.ViewGen_NonKeyProjectedWithOverlappingPartitions((object)MemberPath.PropertiesToUserString((IEnumerable <MemberPath>)memberPathList, false)), (IEnumerable <LeftCellWrapper>) new LeftCellWrapper[2] { this.m_wrapper, node.LeftCellWrapper }, string.Empty)); } return(true); }
// effects: Given a list of node, produces a new list in which all // leaf nodes of the same extent are adjacent to each other. Non-leaf // nodes are also adjacent to each other. CHANGE_[....]_IMPROVE: Merge with GroupByRightExtent private static List <CellTreeNode> GroupLeafChildrenByExtent(List <CellTreeNode> nodes) { // Keep track of leaf cells for each extent KeyToListMap <EntitySetBase, CellTreeNode> extentMap = new KeyToListMap <EntitySetBase, CellTreeNode>(EqualityComparer <EntitySetBase> .Default); List <CellTreeNode> newNodes = new List <CellTreeNode>(); foreach (CellTreeNode node in nodes) { 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 { newNodes.Add(node); } } // Go through the map and add the leaf children newNodes.AddRange(extentMap.AllValues); return(newNodes); }
private bool TryMergeCellQueries( CellTreeOpType opType, ref CellTreeNode node1, CellTreeNode node2) { LeafCellTreeNode leafCellTreeNode1 = node1 as LeafCellTreeNode; LeafCellTreeNode leafCellTreeNode2 = node2 as LeafCellTreeNode; CellQuery mergedQuery1; CellQuery mergedQuery2; if (!CellTreeSimplifier.TryMergeTwoCellQueries(leafCellTreeNode1.LeftCellWrapper.RightCellQuery, leafCellTreeNode2.LeftCellWrapper.RightCellQuery, opType, out mergedQuery1) || !CellTreeSimplifier.TryMergeTwoCellQueries(leafCellTreeNode1.LeftCellWrapper.LeftCellQuery, leafCellTreeNode2.LeftCellWrapper.LeftCellQuery, opType, out mergedQuery2)) { return(false); } OpCellTreeNode opCellTreeNode = new OpCellTreeNode(this.m_viewgenContext, opType); opCellTreeNode.Add(node1); opCellTreeNode.Add(node2); if (opType != CellTreeOpType.FOJ) { ; } LeftCellWrapper cellWrapper = new LeftCellWrapper(this.m_viewgenContext.ViewTarget, opCellTreeNode.Attributes, opCellTreeNode.LeftFragmentQuery, mergedQuery2, mergedQuery1, this.m_viewgenContext.MemberMaps, leafCellTreeNode1.LeftCellWrapper.Cells.Concat <Cell>(leafCellTreeNode2.LeftCellWrapper.Cells)); node1 = (CellTreeNode) new LeafCellTreeNode(this.m_viewgenContext, cellWrapper, opCellTreeNode.RightFragmentQuery); return(true); }
// requires: node1 and node2 are two children of the same parent // connected by opType // effects: Given two cell tree nodes, node1 and node2, runs the // TM/SP rule on them to merge them (if they belong to the same // extent). Returns true if the merge succeeds private bool TryMergeCellQueries( CellTreeOpType opType, ref CellTreeNode node1, CellTreeNode node2) { var leaf1 = node1 as LeafCellTreeNode; var leaf2 = node2 as LeafCellTreeNode; Debug.Assert(leaf1 != null, "Merge only possible on leaf nodes (1)"); Debug.Assert(leaf2 != null, "Merge only possible on leaf nodes (2)"); CellQuery mergedLeftCellQuery; CellQuery mergedRightCellQuery; if ( !TryMergeTwoCellQueries( leaf1.LeftCellWrapper.RightCellQuery, leaf2.LeftCellWrapper.RightCellQuery, opType, out mergedRightCellQuery)) { return(false); } if ( !TryMergeTwoCellQueries( leaf1.LeftCellWrapper.LeftCellQuery, leaf2.LeftCellWrapper.LeftCellQuery, opType, out mergedLeftCellQuery)) { return(false); } // Create a temporary node and add the two children // so that we can get the merged selectiondomains and attributes // Note that temp.SelectionDomain below determines the domain // based on the opType, e.g., for IJ, it intersects the // multiconstants of all the children var temp = new OpCellTreeNode(m_viewgenContext, opType); temp.Add(node1); temp.Add(node2); // Note: We are losing the original cell number information here and the line number information // But we will not raise any // We do not create CellExpressions with LOJ, FOJ - canBooleansOverlap is true for validation var inputOpType = opType; if (opType == CellTreeOpType.FOJ || opType == CellTreeOpType.LOJ) { inputOpType = CellTreeOpType.IJ; } var wrapper = new LeftCellWrapper( m_viewgenContext.ViewTarget, temp.Attributes, temp.LeftFragmentQuery, mergedLeftCellQuery, mergedRightCellQuery, m_viewgenContext.MemberMaps, leaf1.LeftCellWrapper.Cells.Concat(leaf2.LeftCellWrapper.Cells)); node1 = new LeafCellTreeNode(m_viewgenContext, wrapper, temp.RightFragmentQuery); return(true); }
// effects: Given a set of nodes, determines if all nodes are the exact same associative opType AND // there are leaf children that are common across the children "nodes". If there are any, // returns them. Else return null private static Set <LeafCellTreeNode> GetCommonGrandChildren(List <CellTreeNode> nodes) { Set <LeafCellTreeNode> commonLeaves = null; // We could make this general and apply recursively but we don't for now // Look for a tree of the form: (common op2 gc2) op1 (common op2 gc3) op1 (common op2 gc4) // e.g., (A IJ B IJ X IJ Y) UNION (A IJ B IJ Y IJ Z) UNION (A IJ B IJ R IJ S) // Where op1 and op2 are associative and common, gc2 etc are leaf nodes CellTreeOpType commonChildOpType = CellTreeOpType.Leaf; foreach (CellTreeNode node in nodes) { OpCellTreeNode opNode = node as OpCellTreeNode; if (opNode == null) { return(null); } Debug.Assert(opNode.OpType != CellTreeOpType.Leaf, "Leaf type for op cell node?"); // Now check for whether the op is associative and the same as the previous one if (commonChildOpType == CellTreeOpType.Leaf) { commonChildOpType = opNode.OpType; } else if (CellTreeNode.IsAssociativeOp(opNode.OpType) == false || commonChildOpType != opNode.OpType) { return(null); } // Make sure all the children are leaf children Set <LeafCellTreeNode> nodeChildrenSet = new Set <LeafCellTreeNode>(LeafCellTreeNode.EqualityComparer); foreach (CellTreeNode grandChild in opNode.Children) { LeafCellTreeNode leafGrandChild = grandChild as LeafCellTreeNode; if (leafGrandChild == null) { return(null); } nodeChildrenSet.Add(leafGrandChild); } if (commonLeaves == null) { commonLeaves = nodeChildrenSet; } else { commonLeaves.Intersect(nodeChildrenSet); } } if (commonLeaves.Count == 0) { // No restructuring possible return(null); } return(commonLeaves); }
internal CellTreeNode CreateViewExpression() { OpCellTreeNode opCellTreeNode = new OpCellTreeNode(this.m_viewgenContext, CellTreeOpType.FOJ); foreach (LeftCellWrapper usedCell in this.m_usedCells) { LeafCellTreeNode leafCellTreeNode = new LeafCellTreeNode(this.m_viewgenContext, usedCell); opCellTreeNode.Add((CellTreeNode)leafCellTreeNode); } CellTreeNode rootNode = this.IsolateByOperator(this.IsolateByOperator(this.IsolateByOperator(this.IsolateUnions(this.GroupByRightExtent((CellTreeNode)opCellTreeNode)), CellTreeOpType.Union), CellTreeOpType.IJ), CellTreeOpType.LOJ); if (this.m_viewgenContext.ViewTarget == ViewTarget.QueryView) { rootNode = this.ConvertUnionsToNormalizedLOJs(rootNode); } return(rootNode); }
private static Set <LeafCellTreeNode> GetCommonGrandChildren( List <CellTreeNode> nodes) { Set <LeafCellTreeNode> set = (Set <LeafCellTreeNode>)null; CellTreeOpType cellTreeOpType = CellTreeOpType.Leaf; foreach (CellTreeNode node in nodes) { OpCellTreeNode opCellTreeNode = node as OpCellTreeNode; if (opCellTreeNode == null) { return((Set <LeafCellTreeNode>)null); } if (cellTreeOpType == CellTreeOpType.Leaf) { cellTreeOpType = opCellTreeNode.OpType; } else if (!CellTreeNode.IsAssociativeOp(opCellTreeNode.OpType) || cellTreeOpType != opCellTreeNode.OpType) { return((Set <LeafCellTreeNode>)null); } Set <LeafCellTreeNode> other = new Set <LeafCellTreeNode>(LeafCellTreeNode.EqualityComparer); foreach (CellTreeNode child in opCellTreeNode.Children) { LeafCellTreeNode element = child as LeafCellTreeNode; if (element == null) { return((Set <LeafCellTreeNode>)null); } other.Add(element); } if (set == null) { set = other; } else { set.Intersect(other); } } if (set.Count == 0) { return((Set <LeafCellTreeNode>)null); } return(set); }
// 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); }
private static List <CellTreeNode> GroupLeafChildrenByExtent( List <CellTreeNode> nodes) { KeyToListMap <EntitySetBase, CellTreeNode> keyToListMap = new KeyToListMap <EntitySetBase, CellTreeNode>((IEqualityComparer <EntitySetBase>)EqualityComparer <EntitySetBase> .Default); List <CellTreeNode> cellTreeNodeList = new List <CellTreeNode>(); foreach (CellTreeNode node in nodes) { LeafCellTreeNode leafCellTreeNode = node as LeafCellTreeNode; if (leafCellTreeNode != null) { keyToListMap.Add(leafCellTreeNode.LeftCellWrapper.RightCellQuery.Extent, (CellTreeNode)leafCellTreeNode); } else { cellTreeNodeList.Add(node); } } cellTreeNodeList.AddRange(keyToListMap.AllValues); return(cellTreeNodeList); }
internal override bool VisitLeaf(LeafCellTreeNode node, bool dummy) { // make sure all projected attributes in wrapper correspond exactly to those in node var thisQuery = m_wrapper.RightCellQuery; var thatQuery = node.LeftCellWrapper.RightCellQuery; var collidingColumns = new List <MemberPath>(); if (thisQuery != thatQuery) { for (var i = 0; i < thisQuery.NumProjectedSlots; i++) { var thisSlot = thisQuery.ProjectedSlotAt(i) as MemberProjectedSlot; if (thisSlot != null) { var thatSlot = thatQuery.ProjectedSlotAt(i) as MemberProjectedSlot; if (thatSlot != null) { var tableMember = m_viewgenContext.MemberMaps.ProjectedSlotMap[i]; if (!tableMember.IsPartOfKey) { if (!MemberPath.EqualityComparer.Equals(thisSlot.MemberPath, thatSlot.MemberPath)) { collidingColumns.Add(tableMember); } } } } } } if (collidingColumns.Count > 0) { var columnsString = MemberPath.PropertiesToUserString(collidingColumns, false); var message = Strings.ViewGen_NonKeyProjectedWithOverlappingPartitions(columnsString); var record = new ErrorLog.Record( ViewGenErrorCode.NonKeyProjectedWithOverlappingPartitions, message, new[] { m_wrapper, node.LeftCellWrapper }, String.Empty); m_errorLog.AddEntry(record); } return(true); }
// effects: Given the set of used cells for an extent, returns a // view to generate that extent internal CellTreeNode CreateViewExpression() { // Create an initial FOJ group with all the used cells as children var fojNode = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.FOJ); // Add all the used cells as children to fojNode. This is a valid // view for the extent. We later try to optimize it foreach (var cell in m_usedCells) { var cellNode = new LeafCellTreeNode(m_viewgenContext, cell); fojNode.Add(cellNode); } //rootNode = GroupByNesting(rootNode); // Group cells by the "right" extent (recall that we are // generating the view for the left extent) so that cells of the // same extent are in the same subtree var rootNode = GroupByRightExtent(fojNode); // Change some of the FOJs to Unions, IJs and LOJs rootNode = IsolateUnions(rootNode); // The isolation with Union is different from IsolateUnions -- // the above isolation finds collections of chidren in a // node and connects them by union. The below one only considers // two children at a time rootNode = IsolateByOperator(rootNode, CellTreeOpType.Union); rootNode = IsolateByOperator(rootNode, CellTreeOpType.IJ); rootNode = IsolateByOperator(rootNode, CellTreeOpType.LOJ); if (m_viewgenContext.ViewTarget == ViewTarget.QueryView) { rootNode = ConvertUnionsToNormalizedLOJs(rootNode); } return(rootNode); }
// effects: Given the set of used cells for an extent, returns a // view to generate that extent internal CellTreeNode CreateViewExpression() { // Create an initial FOJ group with all the used cells as children var fojNode = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.FOJ); // Add all the used cells as children to fojNode. This is a valid // view for the extent. We later try to optimize it foreach (var cell in m_usedCells) { var cellNode = new LeafCellTreeNode(m_viewgenContext, cell); fojNode.Add(cellNode); } //rootNode = GroupByNesting(rootNode); // Group cells by the "right" extent (recall that we are // generating the view for the left extent) so that cells of the // same extent are in the same subtree var rootNode = GroupByRightExtent(fojNode); // Change some of the FOJs to Unions, IJs and LOJs rootNode = IsolateUnions(rootNode); // The isolation with Union is different from IsolateUnions -- // the above isolation finds collections of chidren in a // node and connects them by union. The below one only considers // two children at a time rootNode = IsolateByOperator(rootNode, CellTreeOpType.Union); rootNode = IsolateByOperator(rootNode, CellTreeOpType.IJ); rootNode = IsolateByOperator(rootNode, CellTreeOpType.LOJ); if (m_viewgenContext.ViewTarget == ViewTarget.QueryView) { rootNode = ConvertUnionsToNormalizedLOJs(rootNode); } return rootNode; }
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); }
private CellTreeNode ConvertUnionsToNormalizedLOJs(CellTreeNode rootNode) { for (int index = 0; index < rootNode.Children.Count; ++index) { rootNode.Children[index] = this.ConvertUnionsToNormalizedLOJs(rootNode.Children[index]); } if (rootNode.OpType != CellTreeOpType.LOJ || rootNode.Children.Count < 2) { return(rootNode); } OpCellTreeNode opCellTreeNode1 = new OpCellTreeNode(this.m_viewgenContext, rootNode.OpType); List <CellTreeNode> cellTreeNodeList = new List <CellTreeNode>(); OpCellTreeNode opCellTreeNode2 = (OpCellTreeNode)null; HashSet <CellTreeNode> cellTreeNodeSet = (HashSet <CellTreeNode>)null; if (rootNode.Children[0].OpType == CellTreeOpType.IJ) { opCellTreeNode2 = new OpCellTreeNode(this.m_viewgenContext, rootNode.Children[0].OpType); opCellTreeNode1.Add((CellTreeNode)opCellTreeNode2); cellTreeNodeList.AddRange((IEnumerable <CellTreeNode>)rootNode.Children[0].Children); cellTreeNodeSet = new HashSet <CellTreeNode>((IEnumerable <CellTreeNode>)rootNode.Children[0].Children); } else { opCellTreeNode1.Add(rootNode.Children[0]); } foreach (CellTreeNode cellTreeNode in rootNode.Children.Skip <CellTreeNode>(1)) { OpCellTreeNode opCellTreeNode3 = cellTreeNode as OpCellTreeNode; if (opCellTreeNode3 != null && opCellTreeNode3.OpType == CellTreeOpType.Union) { cellTreeNodeList.AddRange((IEnumerable <CellTreeNode>)opCellTreeNode3.Children); } else { cellTreeNodeList.Add(cellTreeNode); } } KeyToListMap <EntitySet, LeafCellTreeNode> keyToListMap1 = new KeyToListMap <EntitySet, LeafCellTreeNode>((IEqualityComparer <EntitySet>)EqualityComparer <EntitySet> .Default); foreach (CellTreeNode child in cellTreeNodeList) { LeafCellTreeNode leaf = child as LeafCellTreeNode; if (leaf != null) { EntitySetBase leafNodeTable = (EntitySetBase)BasicViewGenerator.GetLeafNodeTable(leaf); if (leafNodeTable != null) { keyToListMap1.Add((EntitySet)leafNodeTable, leaf); } } else if (cellTreeNodeSet != null && cellTreeNodeSet.Contains(child)) { opCellTreeNode2.Add(child); } else { opCellTreeNode1.Add(child); } } foreach (KeyValuePair <EntitySet, List <LeafCellTreeNode> > keyValuePair in keyToListMap1.KeyValuePairs.Where <KeyValuePair <EntitySet, List <LeafCellTreeNode> > >((Func <KeyValuePair <EntitySet, List <LeafCellTreeNode> >, bool>)(m => m.Value.Count > 1)).ToArray <KeyValuePair <EntitySet, List <LeafCellTreeNode> > >()) { keyToListMap1.RemoveKey(keyValuePair.Key); foreach (LeafCellTreeNode leafCellTreeNode in keyValuePair.Value) { if (cellTreeNodeSet != null && cellTreeNodeSet.Contains((CellTreeNode)leafCellTreeNode)) { opCellTreeNode2.Add((CellTreeNode)leafCellTreeNode); } else { opCellTreeNode1.Add((CellTreeNode)leafCellTreeNode); } } } KeyToListMap <EntitySet, EntitySet> keyToListMap2 = new KeyToListMap <EntitySet, EntitySet>((IEqualityComparer <EntitySet>)EqualityComparer <EntitySet> .Default); Dictionary <EntitySet, OpCellTreeNode> dictionary = new Dictionary <EntitySet, OpCellTreeNode>((IEqualityComparer <EntitySet>)EqualityComparer <EntitySet> .Default); foreach (KeyValuePair <EntitySet, List <LeafCellTreeNode> > keyValuePair in keyToListMap1.KeyValuePairs) { EntitySet key = keyValuePair.Key; foreach (EntitySet fkOverPkDependent in BasicViewGenerator.GetFKOverPKDependents(key)) { ReadOnlyCollection <LeafCellTreeNode> valueCollection; if (keyToListMap1.TryGetListForKey(fkOverPkDependent, out valueCollection) && (cellTreeNodeSet == null || !cellTreeNodeSet.Contains((CellTreeNode)valueCollection.Single <LeafCellTreeNode>()))) { keyToListMap2.Add(key, fkOverPkDependent); } } OpCellTreeNode opCellTreeNode3 = new OpCellTreeNode(this.m_viewgenContext, CellTreeOpType.LOJ); opCellTreeNode3.Add((CellTreeNode)keyValuePair.Value.Single <LeafCellTreeNode>()); dictionary.Add(key, opCellTreeNode3); } Dictionary <EntitySet, EntitySet> nestedExtents = new Dictionary <EntitySet, EntitySet>((IEqualityComparer <EntitySet>)EqualityComparer <EntitySet> .Default); foreach (KeyValuePair <EntitySet, List <EntitySet> > keyValuePair in keyToListMap2.KeyValuePairs) { EntitySet key = keyValuePair.Key; foreach (EntitySet entitySet in keyValuePair.Value) { OpCellTreeNode opCellTreeNode3; if (dictionary.TryGetValue(entitySet, out opCellTreeNode3) && !nestedExtents.ContainsKey(entitySet) && !BasicViewGenerator.CheckLOJCycle(entitySet, key, nestedExtents)) { dictionary[keyValuePair.Key].Add((CellTreeNode)opCellTreeNode3); nestedExtents.Add(entitySet, key); } } } foreach (KeyValuePair <EntitySet, OpCellTreeNode> keyValuePair in dictionary) { if (!nestedExtents.ContainsKey(keyValuePair.Key)) { OpCellTreeNode opCellTreeNode3 = keyValuePair.Value; if (cellTreeNodeSet != null && cellTreeNodeSet.Contains(opCellTreeNode3.Children[0])) { opCellTreeNode2.Add((CellTreeNode)opCellTreeNode3); } else { opCellTreeNode1.Add((CellTreeNode)opCellTreeNode3); } } } return(opCellTreeNode1.Flatten()); }
private static EntitySet GetLeafNodeTable(LeafCellTreeNode leaf) { return(leaf.LeftCellWrapper.RightCellQuery.Extent as EntitySet); }
private static EntitySet GetLeafNodeTable(LeafCellTreeNode leaf) { return leaf.LeftCellWrapper.RightCellQuery.Extent as EntitySet; }
internal void Validate() { // turn rewritings into cell trees // plain: according to rewritings for case statements var plainMemberValueTrees = CreateMemberValueTrees(false); // complement: uses complement rewriting for the last WHEN ... THEN // This is how the final case statement will be generated in update views var complementMemberValueTrees = CreateMemberValueTrees(true); var plainWhereClauseVisitor = new WhereClauseVisitor(_basicView, plainMemberValueTrees); var complementWhereClauseVisitor = new WhereClauseVisitor(_basicView, complementMemberValueTrees); // produce CellTree for each SQuery foreach (var wrapper in _viewgenContext.AllWrappersForExtent) { var cell = wrapper.OnlyInputCell; // construct cell tree for CQuery CellTreeNode cQueryTree = new LeafCellTreeNode(_viewgenContext, wrapper); // sQueryTree: unfolded update view inside S-side of the cell CellTreeNode sQueryTree; // construct cell tree for SQuery (will be used for domain constraint checking) var complementSQueryTreeForCondition = complementWhereClauseVisitor.GetCellTreeNode(cell.SQuery.WhereClause); Debug.Assert(complementSQueryTreeForCondition != null, "Rewriting for S-side query is unsatisfiable"); if (complementSQueryTreeForCondition == null) { continue; // situation should never happen } if (complementSQueryTreeForCondition != _basicView) { // intersect with basic expression sQueryTree = new OpCellTreeNode(_viewgenContext, CellTreeOpType.IJ, complementSQueryTreeForCondition, _basicView); } else { sQueryTree = _basicView; } // Append in-set or in-end condition to both queries to produce more concise errors // Otherwise, the errors are of the form "if there exists an entity in extent, then violation". We don't care about empty extents var inExtentCondition = BoolExpression.CreateLiteral(wrapper.CreateRoleBoolean(), _viewgenContext.MemberMaps.QueryDomainMap); BoolExpression unsatisfiedConstraint; if (!CheckEquivalence( cQueryTree.RightFragmentQuery, sQueryTree.RightFragmentQuery, inExtentCondition, out unsatisfiedConstraint)) { var extentName = StringUtil.FormatInvariant("{0}", _viewgenContext.Extent); // Simplify to produce more readable error messages cQueryTree.RightFragmentQuery.Condition.ExpensiveSimplify(); sQueryTree.RightFragmentQuery.Condition.ExpensiveSimplify(); var message = Strings.ViewGen_CQ_PartitionConstraint(extentName); ReportConstraintViolation( message, unsatisfiedConstraint, ViewGenErrorCode.PartitionConstraintViolation, cQueryTree.GetLeaves().Concat(sQueryTree.GetLeaves())); } var plainSQueryTreeForCondition = plainWhereClauseVisitor.GetCellTreeNode(cell.SQuery.WhereClause); Debug.Assert(plainSQueryTreeForCondition != null, "Rewriting for S-side query is unsatisfiable"); if (plainSQueryTreeForCondition != null) { // Query is non-empty. Check domain constraints on: // (a) swapped members DomainConstraintVisitor.CheckConstraints(plainSQueryTreeForCondition, wrapper, _viewgenContext, _errorLog); //If you have already found errors, just continue on to the next wrapper instead of //collecting more errors for the same if (_errorLog.Count > 0) { continue; } // (b) projected members CheckConstraintsOnProjectedConditionMembers(plainMemberValueTrees, wrapper, sQueryTree, inExtentCondition); if (_errorLog.Count > 0) { continue; } } CheckConstraintsOnNonNullableMembers(wrapper); } if (_errorLog.Count > 0) { ExceptionHelpers.ThrowMappingException(_errorLog, _viewgenContext.Config); } }
// requires: node1 and node2 are two children of the same parent // connected by opType // effects: Given two cell tree nodes, node1 and node2, runs the // TM/SP rule on them to merge them (if they belong to the same // extent). Returns true if the merge succeeds private bool TryMergeCellQueries(CellTreeOpType opType, ref CellTreeNode node1, CellTreeNode node2) { LeafCellTreeNode leaf1 = node1 as LeafCellTreeNode; LeafCellTreeNode leaf2 = node2 as LeafCellTreeNode; Debug.Assert(leaf1 != null, "Merge only possible on leaf nodes (1)"); Debug.Assert(leaf2 != null, "Merge only possible on leaf nodes (2)"); CellQuery mergedLeftCellQuery; CellQuery mergedRightCellQuery; if (!TryMergeTwoCellQueries(leaf1.LeftCellWrapper.RightCellQuery, leaf2.LeftCellWrapper.RightCellQuery, opType, m_viewgenContext.MemberMaps.RightDomainMap, out mergedRightCellQuery)) { return false; } if (!TryMergeTwoCellQueries(leaf1.LeftCellWrapper.LeftCellQuery, leaf2.LeftCellWrapper.LeftCellQuery, opType, m_viewgenContext.MemberMaps.LeftDomainMap, out mergedLeftCellQuery)) { return false; } // Create a temporary node and add the two children // so that we can get the merged selectiondomains and attributes // Note that temp.SelectionDomain below determines the domain // based on the opType, e.g., for IJ, it intersects the // multiconstants of all the children OpCellTreeNode temp = new OpCellTreeNode(m_viewgenContext, opType); temp.Add(node1); temp.Add(node2); // Note: We are losing the original cell number information here and the line number information // But we will not raise any // We do not create CellExpressions with LOJ, FOJ - canBooleansOverlap is true for validation CellTreeOpType inputOpType = opType; if (opType == CellTreeOpType.FOJ || opType == CellTreeOpType.LOJ) { inputOpType = CellTreeOpType.IJ; } LeftCellWrapper wrapper = new LeftCellWrapper(m_viewgenContext.ViewTarget, temp.Attributes, temp.LeftFragmentQuery, mergedLeftCellQuery, mergedRightCellQuery, m_viewgenContext.MemberMaps, leaf1.LeftCellWrapper.Cells.Concat(leaf2.LeftCellWrapper.Cells)); node1 = new LeafCellTreeNode(m_viewgenContext, wrapper, temp.RightFragmentQuery); return true; }