コード例 #1
0
            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);
            }
コード例 #2
0
        // 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);
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        // 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);
        }
コード例 #5
0
        // 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);
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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);
        }
コード例 #8
0
        // 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);
        }
コード例 #9
0
        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);
        }
コード例 #10
0
            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);
            }
コード例 #11
0
ファイル: BasicViewGenerator.cs プロジェクト: dotnet/ef6tools
        // 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);
        }
コード例 #12
0
        // 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;
        }
コード例 #13
0
        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);
        }
コード例 #14
0
        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());
        }
コード例 #15
0
ファイル: BasicViewGenerator.cs プロジェクト: dotnet/ef6tools
 private static EntitySet GetLeafNodeTable(LeafCellTreeNode leaf)
 {
     return(leaf.LeftCellWrapper.RightCellQuery.Extent as EntitySet);
 }
コード例 #16
0
 private static EntitySet GetLeafNodeTable(LeafCellTreeNode leaf)
 {
     return leaf.LeftCellWrapper.RightCellQuery.Extent as EntitySet;
 }
コード例 #17
0
        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);
            }
        }
コード例 #18
0
        // 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;
        }