Ejemplo n.º 1
0
        /// <summary>
        /// Adds the cell below row.
        /// </summary>
        protected void AddCellBelowRow()
        {
            Cell cell = new Cell(Row);

            // get the value string
            StringBuilder val = new StringBuilder();

            int ltmFactor = 1;

            CellTreeNode c = Row.Cells.Min;

            while (c != FirstSelected)
            {
                if (!string.IsNullOrEmpty(c.Cell.Reference))
                {
                    c = c.Next();
                    continue;
                }

                AddCellValueToAccumulator(c.Cell, Row.Cells.Min.Cell, FirstSelected.Cell, val, ref ltmFactor);
                c = c.Next();
            }

            val.Append('0').Append(BeatCell.MultiplyTerms(BeatCell.Invert(DrawingView.Instance.GridSpacingString), NumIntervals));

            cell.Value = BeatCell.Invert(BeatCell.SimplifyValue(val.ToString()));

            // does having negative positions like this cause problems?
            cell.Position = FirstSelected.Cell.Position - DrawingView.Instance.GridSpacing * NumIntervals;
            Row.Cells.Insert(cell);
            RightIndexBoundOfTransform = -1;
            Row.OffsetValue            = BeatCell.Subtract(Row.OffsetValue, cell.Value);  // don't mult group factor this
        }
Ejemplo n.º 2
0
 // Token: 0x06003EAC RID: 16044 RVA: 0x0013BD2C File Offset: 0x0013A12C
 public void GetActiveCells(List <byte> activeCells, bool yIsUpAxis, Vector3 position)
 {
     if (this.NodeType != CellTreeNode.ENodeType.Leaf)
     {
         foreach (CellTreeNode cellTreeNode in this.Childs)
         {
             cellTreeNode.GetActiveCells(activeCells, yIsUpAxis, position);
         }
     }
     else if (this.IsPointNearCell(yIsUpAxis, position))
     {
         if (this.IsPointInsideCell(yIsUpAxis, position))
         {
             activeCells.Insert(0, this.Id);
             for (CellTreeNode parent = this.Parent; parent != null; parent = parent.Parent)
             {
                 activeCells.Insert(0, parent.Id);
             }
         }
         else
         {
             activeCells.Add(this.Id);
         }
     }
 }
        private CellTreeNode IsolateUnions(CellTreeNode rootNode)
        {
            if (rootNode.Children.Count <= 1)
            {
                return(rootNode);
            }
            for (int index = 0; index < rootNode.Children.Count; ++index)
            {
                rootNode.Children[index] = this.IsolateUnions(rootNode.Children[index]);
            }
            OpCellTreeNode opCellTreeNode1 = new OpCellTreeNode(this.m_viewgenContext, CellTreeOpType.Union);
            ModifiableIteratorCollection <CellTreeNode> iteratorCollection = new ModifiableIteratorCollection <CellTreeNode>((IEnumerable <CellTreeNode>)rootNode.Children);

            while (!iteratorCollection.IsEmpty)
            {
                OpCellTreeNode opCellTreeNode2 = new OpCellTreeNode(this.m_viewgenContext, CellTreeOpType.FOJ);
                CellTreeNode   child           = iteratorCollection.RemoveOneElement();
                opCellTreeNode2.Add(child);
                foreach (CellTreeNode element in iteratorCollection.Elements())
                {
                    if (!this.IsDisjoint((CellTreeNode)opCellTreeNode2, element))
                    {
                        opCellTreeNode2.Add(element);
                        iteratorCollection.RemoveCurrentOfIterator();
                        iteratorCollection.ResetIterator();
                    }
                }
                opCellTreeNode1.Add((CellTreeNode)opCellTreeNode2);
            }
            return(opCellTreeNode1.Flatten());
        }
            internal override CellTreeNode VisitTerm(TermExpr <DomainConstraint <BoolLiteral, Constant> > expression)
            {
                var oneOf = (MemberRestriction)expression.Identifier.Variable.Identifier;
                var range = expression.Identifier.Range;

                // create a disjunction
                var          disjunctionNode = new OpCellTreeNode(_viewgenContext, CellTreeOpType.Union);
                CellTreeNode singleNode      = null;

                foreach (var value in range)
                {
                    if (TryGetCellTreeNode(oneOf.RestrictedMemberSlot.MemberPath, value, out singleNode))
                    {
                        disjunctionNode.Add(singleNode);
                    }
                    // else, there is no rewriting for this member value, i.e., it is empty
                }
                switch (disjunctionNode.Children.Count)
                {
                case 0:
                    return(null);    // empty rewriting

                case 1:
                    return(singleNode);

                default:
                    return(disjunctionNode);
                }
            }
Ejemplo n.º 5
0
        protected override void Transformation()
        {
            if (AboveSelection)
            {
                if (Position + 1e-9 >= Row.Cells.Max.Cell.Position + Row.Cells.Max.Cell.Duration)
                {
                    // add above row
                    AddCellAboveRow();
                }
                else
                {
                    // above selection, inside row
                    AddCellToRowAboveSelection();
                }
            }
            else
            {
                if (Position < 0)
                {
                    // in offset region
                    AddCellBelowRow();
                }
                else
                {
                    // below selection, inside row
                    AddCellToRowBelowSelection();
                }
            }

            FirstSelected = null;
            LastSelected  = null;
        }
        // requires: constraint.ChildColumns form a key in
        // constraint.ChildTable (actually they should subsume the primary key)
        private void GuaranteeForeignKeyConstraintInCSpace(QueryRewriter childRewriter, QueryRewriter parentRewriter,
                                                           ErrorLog errorLog, ConfigViewGenerator config)
        {
            ViewgenContext childContext  = childRewriter.ViewgenContext;
            ViewgenContext parentContext = parentRewriter.ViewgenContext;
            CellTreeNode   cNode         = childRewriter.BasicView;
            CellTreeNode   pNode         = parentRewriter.BasicView;

            FragmentQueryProcessor qp = FragmentQueryProcessor.Merge(childContext.RightFragmentQP, parentContext.RightFragmentQP);
            bool cImpliesP            = qp.IsContainedIn(cNode.RightFragmentQuery, pNode.RightFragmentQuery);

            if (false == cImpliesP)
            {
                // Foreign key constraint not being ensured in C-space
                string childExtents  = LeftCellWrapper.GetExtentListAsUserString(cNode.GetLeaves());
                string parentExtents = LeftCellWrapper.GetExtentListAsUserString(pNode.GetLeaves());
                string message       = System.Data.Entity.Strings.ViewGen_Foreign_Key_Not_Guaranteed_InCSpace(
                    ToUserString());
                // Add all wrappers into allWrappers
                Set <LeftCellWrapper> allWrappers = new Set <LeftCellWrapper>(pNode.GetLeaves());
                allWrappers.AddRange(cNode.GetLeaves());
                ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.ForeignKeyNotGuaranteedInCSpace, message, allWrappers, String.Empty);
                errorLog.AddEntry(record);
            }
        }
Ejemplo n.º 7
0
    /// <summary>
    ///     Gathers all cell IDs the player is currently inside or nearby.
    /// </summary>
    /// <param name="activeCells">The list to add all cell IDs to the player is currently inside or nearby.</param>
    /// <param name="yIsUpAxis">Describes if the y-axis is used as up-axis.</param>
    /// <param name="position">The current position of the player.</param>
    public void GetActiveCells(List <byte> activeCells, bool yIsUpAxis, Vector3 position)
    {
        if (this.NodeType != ENodeType.Leaf)
        {
            foreach (CellTreeNode node in this.Childs)
            {
                node.GetActiveCells(activeCells, yIsUpAxis, position);
            }
        }
        else
        {
            if (this.IsPointNearCell(yIsUpAxis, position))
            {
                if (this.IsPointInsideCell(yIsUpAxis, position))
                {
                    activeCells.Insert(0, this.Id);

                    CellTreeNode p = this.Parent;
                    while (p != null)
                    {
                        activeCells.Insert(0, p.Id);

                        p = p.Parent;
                    }
                }
                else
                {
                    activeCells.Add(this.Id);
                }
            }
        }
    }
Ejemplo n.º 8
0
 private bool TryGetCellTreeNode(
     MemberPath memberPath,
     Constant value,
     out CellTreeNode singleNode)
 {
     return(this._memberValueTrees.TryGetValue(new RewritingValidator.MemberValueBinding(memberPath, value), out singleNode));
 }
        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);
        }
 public void GetActiveCells(List <byte> activeCells, bool yIsUpAxis, Vector3 position)
 {
     if (this.NodeType != CellTreeNode.ENodeType.Leaf)
     {
         using (List <CellTreeNode> .Enumerator enumerator = this.Childs.GetEnumerator())
         {
             while (enumerator.MoveNext())
             {
                 CellTreeNode current = enumerator.get_Current();
                 current.GetActiveCells(activeCells, yIsUpAxis, position);
             }
         }
     }
     else if (this.IsPointNearCell(yIsUpAxis, position))
     {
         if (this.IsPointInsideCell(yIsUpAxis, position))
         {
             activeCells.Insert(0, this.Id);
             for (CellTreeNode parent = this.Parent; parent != null; parent = parent.Parent)
             {
                 activeCells.Insert(0, parent.Id);
             }
         }
         else
         {
             activeCells.Add(this.Id);
         }
     }
 }
Ejemplo n.º 11
0
            internal static void CheckConstraints(CellTreeNode node, LeftCellWrapper wrapper,
                                                  ViewgenContext context, ErrorLog errorLog)
            {
                DomainConstraintVisitor visitor = new DomainConstraintVisitor(wrapper, context, errorLog);

                node.Accept <bool, bool>(visitor, true);
            }
Ejemplo n.º 12
0
            internal override CellTreeNode VisitTerm(
                TermExpr <DomainConstraint <BoolLiteral, Constant> > expression)
            {
                MemberRestriction identifier     = (MemberRestriction)expression.Identifier.Variable.Identifier;
                Set <Constant>    range          = expression.Identifier.Range;
                OpCellTreeNode    opCellTreeNode = new OpCellTreeNode(this._viewgenContext, CellTreeOpType.Union);
                CellTreeNode      singleNode     = (CellTreeNode)null;

                foreach (Constant constant in range)
                {
                    if (this.TryGetCellTreeNode(identifier.RestrictedMemberSlot.MemberPath, constant, out singleNode))
                    {
                        opCellTreeNode.Add(singleNode);
                    }
                }
                switch (opCellTreeNode.Children.Count)
                {
                case 0:
                    return((CellTreeNode)null);

                case 1:
                    return(singleNode);

                default:
                    return((CellTreeNode)opCellTreeNode);
                }
            }
        private void AddElseDefaultToCaseStatement(
            MemberPath currentPath,
            CaseStatement caseStatement,
            List <Constant> domain,
            CellTreeNode rightDomainQuery,
            Tile <FragmentQuery> unionCaseRewriting)
        {
            Constant defaultConstant;
            bool     valueForMemberPath = Domain.TryGetDefaultValueForMemberPath(currentPath, out defaultConstant);

            if (valueForMemberPath && domain.Contains(defaultConstant))
            {
                return;
            }
            CellTreeNode  cellTree = QueryRewriter.TileToCellTree(unionCaseRewriting, this._context);
            FragmentQuery query    = this._context.RightFragmentQP.Difference(rightDomainQuery.RightFragmentQuery, cellTree.RightFragmentQuery);

            if (!this._context.RightFragmentQP.IsSatisfiable(query))
            {
                return;
            }
            if (valueForMemberPath)
            {
                caseStatement.AddWhenThen(BoolExpression.True, (ProjectedSlot) new ConstantProjectedSlot(defaultConstant));
            }
            else
            {
                query.Condition.ExpensiveSimplify();
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.AppendLine(Strings.ViewGen_No_Default_Value_For_Configuration((object)currentPath.PathToString(new bool?(false))));
                this._errorLog.AddEntry(new ErrorLog.Record(ViewGenErrorCode.NoDefaultValue, stringBuilder.ToString(), (IEnumerable <LeftCellWrapper>) this._context.AllWrappersForExtent, string.Empty));
            }
        }
Ejemplo n.º 14
0
    private void CreateCellHierarchy()
    {
        if (!this.IsCellCountAllowed())
        {
            if (Debug.get_isDebugBuild())
            {
                Debug.LogError((object)("There are too many cells created by your subdivision options. Maximum allowed number of cells is " + (object)(250 - this.FIRST_GROUP_ID) + ". Current number of cells is " + (object)this.CellCount + "."));
                return;
            }
            Application.Quit();
        }
        CellTreeNode cellTreeNode = new CellTreeNode(this.idCounter++, CellTreeNode.ENodeType.Root, (CellTreeNode)null);

        if (this.YIsUpAxis)
        {
            this.Center              = new Vector2((float)((Component)this).get_transform().get_position().x, (float)((Component)this).get_transform().get_position().y);
            this.Size                = new Vector2((float)((Component)this).get_transform().get_localScale().x, (float)((Component)this).get_transform().get_localScale().y);
            cellTreeNode.Center      = new Vector3((float)this.Center.x, (float)this.Center.y, 0.0f);
            cellTreeNode.Size        = new Vector3((float)this.Size.x, (float)this.Size.y, 0.0f);
            cellTreeNode.TopLeft     = new Vector3((float)(this.Center.x - this.Size.x / 2.0), (float)(this.Center.y - this.Size.y / 2.0), 0.0f);
            cellTreeNode.BottomRight = new Vector3((float)(this.Center.x + this.Size.x / 2.0), (float)(this.Center.y + this.Size.y / 2.0), 0.0f);
        }
        else
        {
            this.Center              = new Vector2((float)((Component)this).get_transform().get_position().x, (float)((Component)this).get_transform().get_position().z);
            this.Size                = new Vector2((float)((Component)this).get_transform().get_localScale().x, (float)((Component)this).get_transform().get_localScale().z);
            cellTreeNode.Center      = new Vector3((float)this.Center.x, 0.0f, (float)this.Center.y);
            cellTreeNode.Size        = new Vector3((float)this.Size.x, 0.0f, (float)this.Size.y);
            cellTreeNode.TopLeft     = new Vector3((float)(this.Center.x - this.Size.x / 2.0), 0.0f, (float)(this.Center.y - this.Size.y / 2.0));
            cellTreeNode.BottomRight = new Vector3((float)(this.Center.x + this.Size.x / 2.0), 0.0f, (float)(this.Center.y + this.Size.y / 2.0));
        }
        this.CreateChildCells(cellTreeNode, 1);
        this.CellTree = new CellTree(cellTreeNode);
        this.RecreateCellHierarchy = false;
    }
Ejemplo n.º 15
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
            var commonChildOpType = CellTreeOpType.Leaf;

            foreach (var node in nodes)
            {
                var 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
                var nodeChildrenSet = new Set <LeafCellTreeNode>(LeafCellTreeNode.EqualityComparer);
                foreach (var grandChild in opNode.Children)
                {
                    var 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);
        }
        // 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);
        }
Ejemplo n.º 17
0
 public void AddChild(CellTreeNode child)
 {
     if (this.Childs == null)
     {
         this.Childs = new List <CellTreeNode>(1);
     }
     this.Childs.Add(child);
 }
Ejemplo n.º 18
0
 internal WhereClauseVisitor(
     CellTreeNode topLevelTree,
     Dictionary <RewritingValidator.MemberValueBinding, CellTreeNode> memberValueTrees)
 {
     this._topLevelTree     = topLevelTree;
     this._memberValueTrees = memberValueTrees;
     this._viewgenContext   = topLevelTree.ViewgenContext;
 }
Ejemplo n.º 19
0
    /// <summary>
    ///     Constructor to define the ID and the node type as well as setting a parent node.
    /// </summary>
    /// <param name="id">The ID of the cell is used as the interest group.</param>
    /// <param name="nodeType">The node type of the cell tree node.</param>
    /// <param name="parent">The parent node of the cell tree node.</param>
    public CellTreeNode(byte id, ENodeType nodeType, CellTreeNode parent)
    {
        this.Id = id;

        this.NodeType = nodeType;

        this.Parent = parent;
    }
 private bool IsEquivalentTo(CellTreeNode n1, CellTreeNode n2)
 {
     if (this.IsContainedIn(n1, n2))
     {
         return(this.IsContainedIn(n2, n1));
     }
     return(false);
 }
 internal RewritingValidator(ViewgenContext context, CellTreeNode basicView)
 {
     _viewgenContext = context;
     _basicView      = basicView;
     _domainMap      = _viewgenContext.MemberMaps.UpdateDomainMap;
     _keyAttributes  = MemberPath.GetKeyMembers(_viewgenContext.Extent, _domainMap);
     _errorLog       = new ErrorLog();
 }
Ejemplo n.º 22
0
 public AddCell(double position, Row row, CellTreeNode firstSelect, CellTreeNode lastSelect) : base(row, "Add Cell")
 {
     FirstSelected = firstSelect;
     LastSelected  = lastSelect;
     //NumIntervals = div;
     //AboveSelection = aboveSelection;
     Position = position;
 }
Ejemplo n.º 23
0
    /// <summary>
    ///     Constructor to define the ID and the node type as well as setting a parent node.
    /// </summary>
    /// <param name="id">The ID of the cell is used as the interest group.</param>
    /// <param name="nodeType">The node type of the cell tree node.</param>
    /// <param name="parent">The parent node of the cell tree node.</param>
    public CellTreeNode(int id, ENodeType nodeType, CellTreeNode parent)
    {
        Id = id;

        NodeType = nodeType;

        Parent = parent;
    }
Ejemplo n.º 24
0
 internal static void CheckConstraints(
     CellTreeNode node,
     LeftCellWrapper wrapper,
     ViewgenContext context,
     ErrorLog errorLog)
 {
     RewritingValidator.DomainConstraintVisitor constraintVisitor = new RewritingValidator.DomainConstraintVisitor(wrapper, context, errorLog);
     node.Accept <bool, bool>((CellTreeNode.SimpleCellTreeVisitor <bool, bool>)constraintVisitor, true);
 }
        private QueryRewriter GenerateViewsForExtentAndType(EdmType generatedType, ViewgenContext context, CqlIdentifiers identifiers, ViewSet views, ViewGenMode mode)
        {
            Debug.Assert(mode != ViewGenMode.GenerateAllViews, "By definition this method can not handle generating views for all extents");

            QueryRewriter queryRewriter = new QueryRewriter(generatedType, context, mode);

            queryRewriter.GenerateViewComponents();

            // Get the basic view
            CellTreeNode basicView = queryRewriter.BasicView;

            if (m_config.IsNormalTracing)
            {
                Helpers.StringTrace("Basic View: ");
                Helpers.StringTraceLine(basicView.ToString());
            }

            CellTreeNode simplifiedView = GenerateSimplifiedView(basicView, queryRewriter.UsedCells);

            if (m_config.IsNormalTracing)
            {
                Helpers.StringTraceLine(String.Empty);
                Helpers.StringTrace("Simplified View: ");
                Helpers.StringTraceLine(simplifiedView.ToString());
            }

            CqlGenerator cqlGen = new CqlGenerator(simplifiedView,
                                                   queryRewriter.CaseStatements,
                                                   identifiers,
                                                   context.MemberMaps.ProjectedSlotMap,
                                                   queryRewriter.UsedCells.Count,
                                                   queryRewriter.TopLevelWhereClause,
                                                   m_entityContainerMapping.StorageMappingItemCollection);

            string             eSQLView;
            DbQueryCommandTree commandTree;

            if (m_config.GenerateEsql)
            {
                eSQLView    = cqlGen.GenerateEsql();
                commandTree = null;
            }
            else
            {
                eSQLView    = null;
                commandTree = cqlGen.GenerateCqt();
            }

            GeneratedView generatedView = GeneratedView.CreateGeneratedView(context.Extent, generatedType, commandTree, eSQLView, m_entityContainerMapping.StorageMappingItemCollection, m_config);

            views.Add(context.Extent, generatedView);

            return(queryRewriter);
        }
Ejemplo n.º 26
0
        private static CellTreeNode GenerateSimplifiedView(
            CellTreeNode basicView,
            List <LeftCellWrapper> usedCells)
        {
            int count = usedCells.Count;

            for (int cellNum = 0; cellNum < count; ++cellNum)
            {
                usedCells[cellNum].RightCellQuery.InitializeBoolExpressions(count, cellNum);
            }
            return(CellTreeSimplifier.MergeNodes(basicView));
        }
 private bool IsContainedIn(CellTreeNode n1, CellTreeNode n2)
 {
     if (this.LeftQP.IsContainedIn(this.LeftQP.Intersect(n1.LeftFragmentQuery, this.m_activeDomain), this.LeftQP.Intersect(n2.LeftFragmentQuery, this.m_activeDomain)))
     {
         return(true);
     }
     return(new OpCellTreeNode(this.m_viewgenContext, CellTreeOpType.LASJ, new CellTreeNode[2]
     {
         n1,
         n2
     }).IsEmptyRightFragmentQuery);
 }
Ejemplo n.º 28
0
    /// <summary>
    ///     Creates all child cells.
    /// </summary>
    /// <param name="parent">The current parent node.</param>
    /// <param name="cellLevelInHierarchy">The cell level within the current hierarchy.</param>
    private void CreateChildCells(CellTreeNode parent, int cellLevelInHierarchy)
    {
        if (cellLevelInHierarchy > this.NumberOfSubdivisions)
        {
            return;
        }

        int rowCount    = (int)this.Subdivisions[(cellLevelInHierarchy - 1)].x;
        int columnCount = (int)this.Subdivisions[(cellLevelInHierarchy - 1)].y;

        float startX = parent.Center.x - (parent.Size.x / 2.0f);
        float width  = parent.Size.x / rowCount;

        for (int row = 0; row < rowCount; ++row)
        {
            for (int column = 0; column < columnCount; ++column)
            {
                float xPos = startX + (row * width) + (width / 2.0f);

                CellTreeNode node = new CellTreeNode(this.idCounter++, (this.NumberOfSubdivisions == cellLevelInHierarchy) ? CellTreeNode.ENodeType.Leaf : CellTreeNode.ENodeType.Node, parent);

                if (this.YIsUpAxis)
                {
                    float startY = parent.Center.y - (parent.Size.y / 2.0f);
                    float height = parent.Size.y / columnCount;
                    float yPos   = startY + (column * height) + (height / 2.0f);

                    node.Center      = new Vector3(xPos, yPos, 0.0f);
                    node.Size        = new Vector3(width, height, 0.0f);
                    node.TopLeft     = new Vector3(xPos - (width / 2.0f), yPos - (height / 2.0f), 0.0f);
                    node.BottomRight = new Vector3(xPos + (width / 2.0f), yPos + (height / 2.0f), 0.0f);
                }
                else
                {
                    float startZ = parent.Center.z - (parent.Size.z / 2.0f);
                    float depth  = parent.Size.z / columnCount;
                    float zPos   = startZ + (column * depth) + (depth / 2.0f);

                    node.Center      = new Vector3(xPos, 0.0f, zPos);
                    node.Size        = new Vector3(width, 0.0f, depth);
                    node.TopLeft     = new Vector3(xPos - (width / 2.0f), 0.0f, zPos - (depth / 2.0f));
                    node.BottomRight = new Vector3(xPos + (width / 2.0f), 0.0f, zPos + (depth / 2.0f));
                }

                parent.AddChild(node);

                this.CreateChildCells(node, (cellLevelInHierarchy + 1));
            }
        }
    }
        private static bool CheckConstraintWhenOnlyParentMapped(
            AssociationSet assocSet,
            AssociationEndMember endMember,
            QueryRewriter childRewriter,
            QueryRewriter parentRewriter)
        {
            ViewgenContext viewgenContext1 = childRewriter.ViewgenContext;
            ViewgenContext viewgenContext2 = parentRewriter.ViewgenContext;
            CellTreeNode   basicView       = parentRewriter.BasicView;
            RoleBoolean    roleBoolean     = new RoleBoolean(assocSet.AssociationSetEnds[endMember.Name]);
            BoolExpression whereClause     = basicView.RightFragmentQuery.Condition.Create((BoolLiteral)roleBoolean);
            FragmentQuery  q1 = FragmentQuery.Create((IEnumerable <MemberPath>)basicView.RightFragmentQuery.Attributes, whereClause);

            return(FragmentQueryProcessor.Merge(viewgenContext1.RightFragmentQP, viewgenContext2.RightFragmentQP).IsContainedIn(q1, basicView.RightFragmentQuery));
        }
Ejemplo n.º 30
0
        private bool IsDisjoint(CellTreeNode n1, CellTreeNode n2)
        {
            var isQueryView = (m_viewgenContext.ViewTarget == ViewTarget.QueryView);

            var isDisjointLeft = LeftQP.IsDisjointFrom(n1.LeftFragmentQuery, n2.LeftFragmentQuery);

            if (isDisjointLeft && m_viewgenContext.ViewTarget == ViewTarget.QueryView)
            {
                return(true);
            }

            CellTreeNode n = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.IJ, n1, n2);
            var          isDisjointRight = n.IsEmptyRightFragmentQuery;

            if (m_viewgenContext.ViewTarget == ViewTarget.UpdateView
                &&
                isDisjointLeft &&
                !isDisjointRight)
            {
                if (ErrorPatternMatcher.FindMappingErrors(m_viewgenContext, m_domainMap, m_errorLog))
                {
                    return(false);
                }

                var builder = new StringBuilder(Strings.Viewgen_RightSideNotDisjoint(m_viewgenContext.Extent.ToString()));
                builder.AppendLine();

                //Retrieve the offending state
                var intersection = LeftQP.Intersect(n1.RightFragmentQuery, n2.RightFragmentQuery);
                if (LeftQP.IsSatisfiable(intersection))
                {
                    intersection.Condition.ExpensiveSimplify();
                    RewritingValidator.EntityConfigurationToUserString(intersection.Condition, builder);
                }

                //Add Error
                m_errorLog.AddEntry(
                    new ErrorLog.Record(
                        ViewGenErrorCode.DisjointConstraintViolation,
                        builder.ToString(), m_viewgenContext.AllWrappersForExtent, String.Empty));

                ExceptionHelpers.ThrowMappingException(m_errorLog, m_config);

                return(false);
            }

            return(isDisjointLeft || isDisjointRight);
        }
Ejemplo n.º 31
0
 /// <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;
 }
        private bool IsContainedIn(CellTreeNode n1, CellTreeNode n2)
        {
            // Decide whether to IJ or LOJ using the domains that are filtered by the active domain
            // The net effect is that some unneeded multiconstants will be pruned away in IJ/LOJ
            // It is desirable to do so since we are only interested in the active domain
            var n1Active = LeftQP.Intersect(n1.LeftFragmentQuery, m_activeDomain);
            var n2Active = LeftQP.Intersect(n2.LeftFragmentQuery, m_activeDomain);

            var isContainedLeft = LeftQP.IsContainedIn(n1Active, n2Active);

            if (isContainedLeft)
            {
                return true;
            }

            CellTreeNode n = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.LASJ, n1, n2);
            var isContainedRight = n.IsEmptyRightFragmentQuery;

            return isContainedRight;
        }
        private bool IsDisjoint(CellTreeNode n1, CellTreeNode n2)
        {
            var isQueryView = (m_viewgenContext.ViewTarget == ViewTarget.QueryView);

            var isDisjointLeft = LeftQP.IsDisjointFrom(n1.LeftFragmentQuery, n2.LeftFragmentQuery);

            if (isDisjointLeft && m_viewgenContext.ViewTarget == ViewTarget.QueryView)
            {
                return true;
            }

            CellTreeNode n = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.IJ, n1, n2);
            var isDisjointRight = n.IsEmptyRightFragmentQuery;

            if (m_viewgenContext.ViewTarget == ViewTarget.UpdateView &&
                isDisjointLeft
                && !isDisjointRight)
            {
                if (ErrorPatternMatcher.FindMappingErrors(m_viewgenContext, m_domainMap, m_errorLog))
                {
                    return false;
                }

                var builder = new StringBuilder(Strings.Viewgen_RightSideNotDisjoint(m_viewgenContext.Extent.ToString()));
                builder.AppendLine();

                //Retrieve the offending state
                var intersection = LeftQP.Intersect(n1.RightFragmentQuery, n2.RightFragmentQuery);
                if (LeftQP.IsSatisfiable(intersection))
                {
                    intersection.Condition.ExpensiveSimplify();
                    RewritingValidator.EntityConfigurationToUserString(intersection.Condition, builder);
                }

                //Add Error
                m_errorLog.AddEntry(
                    new ErrorLog.Record(
                        ViewGenErrorCode.DisjointConstraintViolation,
                        builder.ToString(), m_viewgenContext.AllWrappersForExtent, String.Empty));

                ExceptionHelpers.ThrowMappingException(m_errorLog, m_config);

                return false;
            }

            return (isDisjointLeft || isDisjointRight);
        }
        // effects: Determines if the childNode can be added as a child of the
        // groupNode using te operation "opTypeToIsolate". E.g., if
        // opTypeToIsolate is inner join, we can add child to group node if
        // childNode and groupNode have the same multiconstantsets, i.e., they have
        // the same selection condition
        // Modifies groupNode to contain groupNode at the appropriate
        // position (for LOJs, the child could be added to the beginning)
        private bool TryAddChildToGroup(
            CellTreeOpType opTypeToIsolate, CellTreeNode childNode,
            OpCellTreeNode groupNode)
        {
            switch (opTypeToIsolate)
            {
                case CellTreeOpType.IJ:
                    // For Inner join, the constants of the node and
                    // the child must be the same, i.e., if the cells
                    // are producing exactly same tuples (same selection)
                    if (IsEquivalentTo(childNode, groupNode))
                    {
                        groupNode.Add(childNode);
                        return true;
                    }
                    break;

                case CellTreeOpType.LOJ:
                    // If one cell's selection condition subsumes
                    // another, we can use LOJ. We need to check for
                    // "subsumes" on both sides
                    if (IsContainedIn(childNode, groupNode))
                    {
                        groupNode.Add(childNode);
                        return true;
                    }
                    else if (IsContainedIn(groupNode, childNode))
                    {
                        // child subsumes the whole group -- add it first
                        groupNode.AddFirst(childNode);
                        return true;
                    }
                    break;

                case CellTreeOpType.Union:
                    // If the selection conditions are disjoint, we can use UNION ALL
                    // We cannot use active domain here; disjointness is guaranteed only
                    // if we check the entire selection domain
                    if (IsDisjoint(childNode, groupNode))
                    {
                        groupNode.Add(childNode);
                        return true;
                    }
                    break;
            }
            return false;
        }
        // requires: opTypeToIsolate must be LOJ, IJ, or Union
        // effects: Given a tree rooted at rootNode, determines if there
        // are any FOJs that can be replaced by opTypeToIsolate. If so,
        // does that and a returns a new tree with the replaced operators
        // Note: Method may modify rootNode's contents and children
        internal CellTreeNode IsolateByOperator(CellTreeNode rootNode, CellTreeOpType opTypeToIsolate)
        {
            Debug.Assert(
                opTypeToIsolate == CellTreeOpType.IJ || opTypeToIsolate == CellTreeOpType.LOJ
                || opTypeToIsolate == CellTreeOpType.Union,
                "IsolateJoins can only be called for IJs, LOJs, and Unions");

            var children = rootNode.Children;
            if (children.Count <= 1)
            {
                // No child or one child -  do nothing
                return rootNode;
            }

            // Replace the FOJs with IJs/LOJs/Unions in the children's subtrees first
            for (var i = 0; i < children.Count; i++)
            {
                // Method modifies input as well
                children[i] = IsolateByOperator(children[i], opTypeToIsolate);
            }
            // Only FOJs and LOJs can be coverted (to IJs, Unions, LOJs) --
            // so if the node is not that, we can ignore it (or if the node is already of
            // the same type that we want)
            if (rootNode.OpType != CellTreeOpType.FOJ && rootNode.OpType != CellTreeOpType.LOJ
                ||
                rootNode.OpType == opTypeToIsolate)
            {
                return rootNode;
            }

            // Create a new node with the same type as the input cell node type
            var newRootNode = new OpCellTreeNode(m_viewgenContext, rootNode.OpType);

            // We start a new "group" with one of the children X - we create
            // a newChildNode with type "opTypeToIsolate". Then we
            // determine if any of the remaining children should be in the
            // same group as X.

            // childrenSet keeps track of the children that need to be procesed/partitioned
            var childrenSet = new ModifiableIteratorCollection<CellTreeNode>(children);

            // Find groups with same or subsumed constants and create a join
            // or union node for them. We do this so that some of the FOJs
            // can be replaced by union and join nodes
            // 
            while (false == childrenSet.IsEmpty)
            {
                // Start a new "group" with some child  node (for the opTypeToIsolate node type)

                var groupNode = new OpCellTreeNode(m_viewgenContext, opTypeToIsolate);
                var someChild = childrenSet.RemoveOneElement();
                groupNode.Add(someChild);

                // Go through the remaining children and determine if their
                // constants are subsets/equal/disjoint w.r.t the joinNode
                // constants.

                foreach (var child in childrenSet.Elements())
                {
                    // Check if we can add the child as part of this
                    // groupNode (with opTypeToIsolate being LOJ, IJ, or Union)
                    if (TryAddChildToGroup(opTypeToIsolate, child, groupNode))
                    {
                        childrenSet.RemoveCurrentOfIterator();

                        // For LOJ, suppose that child A did not subsume B or
                        // vice-versa. But child C subsumes both. To ensure
                        // that we can get A, B, C in the same group, we
                        // reset the iterator so that when C is added in B's
                        // loop, we can reconsider A.
                        //
                        // For IJ, adding a child to groupNode does not change the range of it,
                        // so there is no need to reconsider previously skipped children.
                        //
                        // For Union, adding a child to groupNode increases the range of the groupNode,
                        // hence previously skipped (because they weren't disjoint with groupNode) children will continue 
                        // being ignored because they would still have an overlap with one of the nodes inside groupNode.

                        if (opTypeToIsolate == CellTreeOpType.LOJ)
                        {
                            childrenSet.ResetIterator();
                        }
                    }
                }
                // The new Union/LOJ/IJ node needs to be connected to the root
                newRootNode.Add(groupNode);
            }
            return newRootNode.Flatten();
        }
        private CellTreeNode ConvertUnionsToNormalizedLOJs(CellTreeNode rootNode)
        {
            // Recursively, transform the subtrees rooted at rootNode's children.
            for (var i = 0; i < rootNode.Children.Count; i++)
            {
                // Method modifies input as well.
                rootNode.Children[i] = ConvertUnionsToNormalizedLOJs(rootNode.Children[i]);
            }

            // We rewrite only LOJs.
            if (rootNode.OpType != CellTreeOpType.LOJ
                || rootNode.Children.Count < 2)
            {
                return rootNode;
            }

            // Create the resulting LOJ node.
            var result = new OpCellTreeNode(m_viewgenContext, rootNode.OpType);

            // Create working collection for the LOJ children.
            var children = new List<CellTreeNode>();

            // If rootNode looks something like ((V0 IJ V1) LOJ V2 LOJ V3),
            // and it turns out that there are FK associations from V2 or V3 pointing, let's say at V0,
            // then we want to rewrite the result as (V1 IJ (V0 LOJ V2 LOJ V3)).
            // If we don't do this, then plan compiler won't have a chance to eliminate LOJ V2 LOJ V3.
            // Hence, flatten the first child or rootNode if it's IJ, but remember that its parts are driving nodes for the LOJ,
            // so that we don't accidentally nest them.
            OpCellTreeNode resultIJDriver = null;
            HashSet<CellTreeNode> resultIJDriverChildren = null;
            if (rootNode.Children[0].OpType
                == CellTreeOpType.IJ)
            {
                // Create empty resultIJDriver node and add it as the first child (driving) into the LOJ result.
                resultIJDriver = new OpCellTreeNode(m_viewgenContext, rootNode.Children[0].OpType);
                result.Add(resultIJDriver);

                children.AddRange(rootNode.Children[0].Children);
                resultIJDriverChildren = new HashSet<CellTreeNode>(rootNode.Children[0].Children);
            }
            else
            {
                result.Add(rootNode.Children[0]);
            }

            // Flatten unions in non-driving nodes: (V0 LOJ (V1 Union V2 Union V3)) -> (V0 LOJ V1 LOJ V2 LOJ V3) 
            foreach (var child in rootNode.Children.Skip(1))
            {
                var opNode = child as OpCellTreeNode;
                if (opNode != null
                    && opNode.OpType == CellTreeOpType.Union)
                {
                    children.AddRange(opNode.Children);
                }
                else
                {
                    children.Add(child);
                }
            }

            // A dictionary that maps an extent to the nodes that are from that extent.
            // We want a ref comparer here.
            var extentMap = new KeyToListMap<EntitySet, LeafCellTreeNode>(EqualityComparer<EntitySet>.Default);
            // Note that we skip non-leaf nodes (non-leaf nodes don't have FKs) and attach them directly to the result.
            foreach (var child in children)
            {
                var leaf = child as LeafCellTreeNode;
                if (leaf != null)
                {
                    EntitySetBase extent = GetLeafNodeTable(leaf);
                    if (extent != null)
                    {
                        extentMap.Add((EntitySet)extent, leaf);
                    }
                }
                else
                {
                    if (resultIJDriverChildren != null
                        && resultIJDriverChildren.Contains(child))
                    {
                        resultIJDriver.Add(child);
                    }
                    else
                    {
                        result.Add(child);
                    }
                }
            }

            // We only deal with simple cases - one node per extent, remove the rest from children and attach directly to result.
            var nonTrivial = extentMap.KeyValuePairs.Where(m => m.Value.Count > 1).ToArray();
            foreach (var m in nonTrivial)
            {
                extentMap.RemoveKey(m.Key);
                foreach (var n in m.Value)
                {
                    if (resultIJDriverChildren != null
                        && resultIJDriverChildren.Contains(n))
                    {
                        resultIJDriver.Add(n);
                    }
                    else
                    {
                        result.Add(n);
                    }
                }
            }
            Debug.Assert(extentMap.KeyValuePairs.All(m => m.Value.Count == 1), "extentMap must map to single nodes only.");

            // Walk the extents in extentMap and for each extent build PK -> FK1(PK1), FK2(PK2), ... map
            // where PK is the primary key of the left extent, and FKn(PKn) is an FK of a right extent that 
            // points to the PK of the left extent and is based on the PK columns of the right extent.
            // Example:
            //           table tBaseType(Id int, c1 int), PK = (tBaseType.Id)
            //           table tDerivedType1(Id int, c2 int), PK1 = (tDerivedType1.Id), FK1 = (tDerivedType1.Id -> tBaseType.Id)
            //           table tDerivedType2(Id int, c3 int), PK2 = (tDerivedType2.Id), FK2 = (tDerivedType2.Id -> tBaseType.Id)
            // Will produce:
            //           (tBaseType) -> (tDerivedType1, tDerivedType2)
            var pkFkMap = new KeyToListMap<EntitySet, EntitySet>(EqualityComparer<EntitySet>.Default);
            // Also for each extent in extentMap, build another map (extent) -> (LOJ node).
            // It will be used to construct the nesting in the next step.
            var extentLOJs = new Dictionary<EntitySet, OpCellTreeNode>(EqualityComparer<EntitySet>.Default);
            foreach (var extentInfo in extentMap.KeyValuePairs)
            {
                var principalExtent = extentInfo.Key;
                foreach (var fkExtent in GetFKOverPKDependents(principalExtent))
                {
                    // Only track fkExtents that are in extentMap.
                    ReadOnlyCollection<LeafCellTreeNode> nodes;
                    if (extentMap.TryGetListForKey(fkExtent, out nodes))
                    {
                        // Make sure that we are not adding resultIJDriverChildren as FK dependents - we do not want them to get nested.
                        if (resultIJDriverChildren == null
                            || !resultIJDriverChildren.Contains(nodes.Single()))
                        {
                            pkFkMap.Add(principalExtent, fkExtent);
                        }
                    }
                }
                var extentLojNode = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.LOJ);
                extentLojNode.Add(extentInfo.Value.Single());
                extentLOJs.Add(principalExtent, extentLojNode);
            }

            // Construct LOJ nesting inside extentLOJs based on the information in pkFkMap.
            // Also, track nested extents using nestedExtents.
            // Example:
            // We start with nestedExtents empty extentLOJs as such:
            //      tBaseType -> LOJ(BaseTypeNode)
            //      tDerivedType1 -> LOJ(DerivedType1Node)*
            //      tDerivedType2 -> LOJ(DerivedType2Node)**
            // Note that * and ** represent object references. So each time something is nested, 
            // we don't clone, but nest the original LOJ. When we get to processing the extent of that LOJ,
            // we might add other children to that nested LOJ.
            // As we walk pkFkMap, we end up with this:
            //      tBaseType -> LOJ(BaseTypeNode, LOJ(DerivedType1Node)*, LOJ(DerivedType2Node)**)
            //      tDerivedType1 -> LOJ(DerivedType1Node)*
            //      tDerivedType2 -> LOJ(DerivedType2Node)**
            // nestedExtens = (tDerivedType1, tDerivedType2)
            var nestedExtents = new Dictionary<EntitySet, EntitySet>(EqualityComparer<EntitySet>.Default);
            foreach (var m in pkFkMap.KeyValuePairs)
            {
                var principalExtent = m.Key;
                foreach (var fkExtent in m.Value)
                {
                    OpCellTreeNode fkExtentLOJ;
                    if (extentLOJs.TryGetValue(fkExtent, out fkExtentLOJ) &&
                        // make sure we don't nest twice and we don't create a cycle.
                        !nestedExtents.ContainsKey(fkExtent)
                        && !CheckLOJCycle(fkExtent, principalExtent, nestedExtents))
                    {
                        extentLOJs[m.Key].Add(fkExtentLOJ);
                        nestedExtents.Add(fkExtent, principalExtent);
                    }
                }
            }

            // Now we need to grab the LOJs that have not been nested and add them to the result.
            // All LOJs that have been nested must be somewhere inside the LOJs that have not been nested,
            // so they as well end up in the result as part of the unnested ones.
            foreach (var m in extentLOJs)
            {
                if (!nestedExtents.ContainsKey(m.Key))
                {
                    // extentLOJ represents (Vx LOJ Vy LOJ(Vm LOJ Vn)) where Vx is the original node from rootNode.Children or resultIJDriverChildren.
                    var extentLOJ = m.Value;
                    if (resultIJDriverChildren != null
                        && resultIJDriverChildren.Contains(extentLOJ.Children[0]))
                    {
                        resultIJDriver.Add(extentLOJ);
                    }
                    else
                    {
                        result.Add(extentLOJ);
                    }
                }
            }

            return result.Flatten();
        }
        // requires: cellTreeNode has a tree such that all its intermediate nodes
        // are FOJ nodes only
        // effects: Converts the tree rooted at rootNode (recursively) in
        // following way and returns a new rootNode -- it partitions
        // rootNode's children such that no two different partitions have
        // any overlapping constants. These partitions are connected by Union
        // nodes (since there is no overlapping).
        // Note: Method may modify rootNode's contents and children
        private CellTreeNode IsolateUnions(CellTreeNode rootNode)
        {
            if (rootNode.Children.Count <= 1)
            {
                // No partitioning of children needs to be done
                return rootNode;
            }

            Debug.Assert(rootNode.OpType == CellTreeOpType.FOJ, "So far, we have FOJs only");

            // Recursively, transform the subtrees rooted at cellTreeNode's children
            for (var i = 0; i < rootNode.Children.Count; i++)
            {
                // Method modifies input as well
                rootNode.Children[i] = IsolateUnions(rootNode.Children[i]);
            }

            // Different children groups are connected by a Union
            // node -- the secltion domain of one group is disjoint from
            // another group's selection domain, i.e., group A1 contributes
            // tuples to the extent which are disjoint from the tuples by
            // A2. So we can connect these groups by union alls.
            // Inside each group, we continue to connect children of the same
            // group using FOJ
            var unionNode = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.Union);

            // childrenSet keeps track of the children that need to be procesed/partitioned
            var childrenSet = new ModifiableIteratorCollection<CellTreeNode>(rootNode.Children);

            while (false == childrenSet.IsEmpty)
            {
                // Start a new group
                // Make an FOJ node to connect children of the same group
                var fojNode = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.FOJ);

                // Add one of the root's children as a child to the foj node
                var someChild = childrenSet.RemoveOneElement();
                fojNode.Add(someChild);

                // We now want a transitive closure of the overlap between the 
                // the children node. We keep checking each child with the
                // fojNode and add it as a child of fojNode if there is an
                // overlap. Note that when a node is added to the fojNode,
                // its constants are propagated to the fojNode -- so we do
                // get transitive closure in terms of intersection 
                foreach (var child in childrenSet.Elements())
                {
                    if (!IsDisjoint(fojNode, child))
                    {
                        fojNode.Add(child);
                        childrenSet.RemoveCurrentOfIterator();
                        // To ensure that we get all overlapping node, we
                        // need to restart checking all the children
                        childrenSet.ResetIterator();
                    }
                }
                // Now we have a group of children nodes rooted at
                // fojNode. Add this fojNode to the union
                unionNode.Add(fojNode);
            }

            // The union node as the root of the view
            var result = unionNode.Flatten();
            return result;
        }
        // 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();
        }
Ejemplo n.º 39
0
        private void AddElseDefaultToCaseStatement(
            MemberPath currentPath, CaseStatement caseStatement, List<Constant> domain,
            CellTreeNode rightDomainQuery, Tile<FragmentQuery> unionCaseRewriting)
        {
            Debug.Assert(_context.ViewTarget == ViewTarget.UpdateView, "Used for update views only");

            Constant defaultValue;
            var hasDefaultValue = Domain.TryGetDefaultValueForMemberPath(currentPath, out defaultValue);

            if (false == hasDefaultValue
                || false == domain.Contains(defaultValue))
            {
                Debug.Assert(unionCaseRewriting != null, "No union of rewritings for case statements");
                var unionTree = TileToCellTree(unionCaseRewriting, _context);
                var configurationNeedsDefault = _context.RightFragmentQP.Difference(
                    rightDomainQuery.RightFragmentQuery, unionTree.RightFragmentQuery);

                if (_context.RightFragmentQP.IsSatisfiable(configurationNeedsDefault))
                {
                    if (hasDefaultValue)
                    {
                        caseStatement.AddWhenThen(BoolExpression.True, new ConstantProjectedSlot(defaultValue));
                    }
                    else
                    {
                        configurationNeedsDefault.Condition.ExpensiveSimplify();
                        var builder = new StringBuilder();
                        builder.AppendLine(
                            Strings.ViewGen_No_Default_Value_For_Configuration(currentPath.PathToString(false /* for alias */)));
                        _errorLog.AddEntry(
                            new ErrorLog.Record(
                                ViewGenErrorCode.NoDefaultValue, builder.ToString(), _context.AllWrappersForExtent, String.Empty));
                    }
                }
            }
        }
 private bool IsEquivalentTo(CellTreeNode n1, CellTreeNode n2)
 {
     return IsContainedIn(n1, n2) && IsContainedIn(n2, n1);
 }
        // effects: Restructure tree so that it is better positioned for merges
        private CellTreeNode RestructureTreeForMerges(CellTreeNode rootNode)
        {
            List<CellTreeNode> children = rootNode.Children;
            if (CellTreeNode.IsAssociativeOp(rootNode.OpType) == false || children.Count <= 1)
            {
                return rootNode;
            }

            // If this node's operator is associative and each child's
            // operator is also associative, check if there is a common set
            // of leaf nodes across all grandchildren

            Set<LeafCellTreeNode> commonGrandChildren = GetCommonGrandChildren(children);
            if (commonGrandChildren == null)
            {
                return rootNode;
            }

            CellTreeOpType commonChildOpType = children[0].OpType;

            //  We do have the structure that we are looking for
            // (common op2 gc2) op1 (common op2 gc3) op1 (common op2 gc4) becomes
            // common op2 (gc2 op1 gc3 op1 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)
            // becomes A IJ B IJ ((X IJ Y) UNION (Y IJ Z) UNION (R IJ S))

            // From each child in children, get the nodes other than commonGrandChildren - these are gc2, gc3, ...
            // Each gc2 must be connected by op2 as before, i.e., ABC + ACD = A(BC + CD)

            // All children must be OpCellTreeNodes!
            List<OpCellTreeNode> newChildren = new List<OpCellTreeNode>(children.Count);
            foreach (OpCellTreeNode child in children)
            {
                // Remove all children in child that belong to commonGrandChildren
                // All grandChildren must be leaf nodes at this point
                List<LeafCellTreeNode> newGrandChildren = new List<LeafCellTreeNode>(child.Children.Count);
                foreach (LeafCellTreeNode grandChild in child.Children)
                {
                    if (commonGrandChildren.Contains(grandChild) == false)
                    {
                        newGrandChildren.Add(grandChild);
                    }
                }
                // In the above example, child.OpType is IJ
                Debug.Assert(child.OpType == commonChildOpType);
                OpCellTreeNode newChild = new OpCellTreeNode(m_viewgenContext, child.OpType,
                                                             Helpers.AsSuperTypeList<LeafCellTreeNode, CellTreeNode>(newGrandChildren));
                newChildren.Add(newChild);
            }
            // Connect gc2 op1 gc3 op1 gc4 - op1 is UNION in this
            // ((X IJ Y) UNION (Y IJ Z) UNION (R IJ S))
            // rootNode.Type is UNION
            CellTreeNode remainingNodes = new OpCellTreeNode(m_viewgenContext, rootNode.OpType,
                                                             Helpers.AsSuperTypeList<OpCellTreeNode, CellTreeNode>(newChildren));
            // Take the common grandchildren and connect via commonChildType
            // i.e., A IJ B
            CellTreeNode commonNodes = new OpCellTreeNode(m_viewgenContext, commonChildOpType,
                                                            Helpers.AsSuperTypeList<LeafCellTreeNode, CellTreeNode>(commonGrandChildren));

            // Connect both by commonChildType
            CellTreeNode result = new OpCellTreeNode(m_viewgenContext, commonChildOpType,
                                                     new CellTreeNode[] { commonNodes, remainingNodes });

            result = result.AssociativeFlatten();
            return result;
        }
        // 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;
        }
 // effects: see CellTreeNode.Simplify below
 internal static CellTreeNode MergeNodes(CellTreeNode rootNode)
 {
     CellTreeSimplifier simplifier = new CellTreeSimplifier(rootNode.ViewgenContext);
     return simplifier.SimplifyTreeByMergingNodes(rootNode);
 }
        // effects: Simplifies the tree rooted at rootNode and returns a new
        // tree -- it ensures that the returned tree has at most one node for
        // any particular extent unless the tree has nodes of the same extent
        // embedded two leaves below LASJ or LOJ, e.g., if we have a tree
        // (where Ni indicates a node for extent i - one Ni can be different
        // from anohter Ni: 
        // [N0 IJ N1] LASJ N0 --> This will not be simplified
        // canBooleansOverlap indicates whether an original input cell
        // contributes to multiple nodes in this tree, e.g., V1 IJ V2 UNION V2 IJ V3
        private CellTreeNode SimplifyTreeByMergingNodes(CellTreeNode rootNode)
        {

            if (rootNode is LeafCellTreeNode)
            { // View already simple!
                return rootNode;
            }
            Debug.Assert(rootNode.OpType == CellTreeOpType.LOJ || rootNode.OpType == CellTreeOpType.IJ ||
                         rootNode.OpType == CellTreeOpType.FOJ || rootNode.OpType == CellTreeOpType.Union ||
                         rootNode.OpType == CellTreeOpType.LASJ,
                         "Only handle these operations");

            // Before we apply any rule, check if we can improve the opportunity to
            // collapse the nodes
            rootNode = RestructureTreeForMerges(rootNode);

            List<CellTreeNode> children = rootNode.Children;
            Debug.Assert(children.Count > 0, "OpCellTreeNode has no children?");

            // Apply recursively
            for (int i = 0; i < children.Count; i++)
            {
                children[i] = SimplifyTreeByMergingNodes(children[i]);
            }

            // Essentially, we have a node with IJ, LOJ, U or FOJ type that
            // has some children. Check if some of the children can be merged
            // with one another using the corresponding TM/SP rule

            // Ops such as IJ, Union and FOJ are associative, i.e., A op (B
            // op C) is the same as (A op B) op C. This is not true for LOJ
            // and LASJ
            bool isAssociativeOp = CellTreeNode.IsAssociativeOp(rootNode.OpType);
            if (isAssociativeOp)
            {
                // Group all the leaf cells of an extent together so that we can
                // later simply run through them without running nested loops
                // We do not do this for LOJ/LASJ nodes since LOJ (LASJ) is not commutative
                // (or associative);
                children = GroupLeafChildrenByExtent(children);
            }
            else
            {
                children = GroupNonAssociativeLeafChildren(children);
            }

            // childrenSet keeps track of the children that need to be procesed/partitioned
            OpCellTreeNode newNode = new OpCellTreeNode(m_viewgenContext, rootNode.OpType);
            CellTreeNode lastChild = null;
            bool skipRest = false;
            foreach (CellTreeNode child in children)
            {
                if (lastChild == null)
                {
                    // First time in the loop. Just set lastChild
                    lastChild = child;
                    continue;
                }

                bool mergedOk = false;
                // try to merge lastChild and child
                if (false == skipRest && lastChild.OpType == CellTreeOpType.Leaf &&
                    child.OpType == CellTreeOpType.Leaf)
                {
                    // Both are cell queries. Can try to merge them
                    // We do not add lastChild since it could merge
                    // further. It will be added in a later loop or outside the loop
                    mergedOk = TryMergeCellQueries(rootNode.OpType, ref lastChild, child);
                }

                if (false == mergedOk)
                {
                    // No merge occurred. Simply add the previous child as it
                    // is (Note lastChild will be added in the next loop or if
                    // the loop finishes, outside the loop
                    newNode.Add(lastChild);
                    lastChild = child;
                    if (false == isAssociativeOp)
                    {
                        // LOJ is not associative:
                        // (P loj PA) loj PO != P loj (PA loj PO). The RHS does not have
                        // Persons who have orders but no addresses
                        skipRest = true;
                    }
                }
            }

            newNode.Add(lastChild);
            CellTreeNode result = newNode.AssociativeFlatten();
            return result;
        }
Ejemplo n.º 45
0
        private static CellTreeNode GenerateSimplifiedView(CellTreeNode basicView, List<LeftCellWrapper> usedCells)
        {
            Debug.Assert(false == basicView.IsEmptyRightFragmentQuery, "Basic view is empty?");

            // create 'joined' variables, one for each cell
            // We know (say) that out of the 10 cells that we were given, only 7 (say) were
            // needed to construct the view for this extent.
            var numBoolVars = usedCells.Count;
            // We need the boolean expressions in Simplify. Precisely ont boolean expression is set to
            // true in each cell query

            for (var i = 0; i < numBoolVars; i++)
            {
                // In the ith cell, set its boolean to be true (i.e., ith boolean)
                usedCells[i].RightCellQuery.InitializeBoolExpressions(numBoolVars, i);
            }

            var simplifiedView = CellTreeSimplifier.MergeNodes(basicView);
            return simplifiedView;
        }
Ejemplo n.º 46
0
        // Generates the components used to assemble and validate the view:
        // (1) case statements
        // (2) top-level where clause
        // (3) used cells
        // (4) basic view CellTreeNode
        // (5) dictionary<MemberValue, CellTreeNode> for validation
        internal void GenerateViewComponents()
        {
            // make sure everything is mapped (for query views only)
            EnsureExtentIsFullyMapped(_usedViews);

            // (1) case statements
            GenerateCaseStatements(_domainMap.ConditionMembers(_extentPath.Extent), _usedViews);

            AddTrivialCaseStatementsForConditionMembers();

            if (_usedViews.Count == 0
                || _errorLog.Count > 0)
            {
                // can't continue: no view will be generated, further validation doesn't make sense
                Debug.Assert(_errorLog.Count > 0);
                ExceptionHelpers.ThrowMappingException(_errorLog, _config);
            }

            // (2) top-level where clause
            _topLevelWhereClause = GetTopLevelWhereClause(_usedViews);

            // some tracing
            if (_context.ViewTarget
                == ViewTarget.QueryView)
            {
                TraceVerbose("Used {0} views of {1} total for rewriting", _usedViews.Count, _views.Count);
            }
            PrintStatistics(_qp);

            // (3) construct the final _from variables
            _usedCells = RemapFromVariables();

            // (4) construct basic view
            var basicViewGenerator = new BasicViewGenerator(
                _context.MemberMaps.ProjectedSlotMap, _usedCells,
                _domainQuery, _context, _domainMap, _errorLog, _config);

            _basicView = basicViewGenerator.CreateViewExpression();

            // a top-level WHERE clause is needed only if the simplifiedView still contains extra tuples
            var noWhereClauseNeeded = _context.LeftFragmentQP.IsContainedIn(_basicView.LeftFragmentQuery, _domainQuery);
            if (noWhereClauseNeeded)
            {
                _topLevelWhereClause = BoolExpression.True;
            }

            if (_errorLog.Count > 0)
            {
                ExceptionHelpers.ThrowMappingException(_errorLog, _config);
            }
        }