Example #1
0
 internal bool TryGetNode(string alias, out CompileNode node)
 {
     if (this.NonFreeTables.ContainsKey(alias))
     {
         node = this.NonFreeTables[alias];
         return(true);
     }
     else
     {
         MatchNode matchNode;
         if (this.GraphPattern.TryGetNode(alias, out matchNode))
         {
             node = matchNode;
             return(true);
         }
     }
     node = null;
     return(false);
 }
Example #2
0
        /// <summary>
        /// Given a node / TVF, a traversalLink and backwardEdges, try to find all predicates that can be evaluated
        /// </summary>
        /// <param name="node"></param>
        /// <param name="traversalLink"></param>
        /// <param name="backwardEdges"></param>
        /// <param name="predicateLinksAccessedTableAliases"></param>
        private List <Tuple <PredicateLink, int> > FindPredicates(
            CompileNode node,
            CompileLink traversalLink,
            List <Tuple <MatchEdge, int> > backwardEdges,
            List <Tuple <PredicateLink, HashSet <string> > > predicateLinksAccessedTableAliases)
        {
            // Record temporary aliases and predicates
            HashSet <string> temporaryAliases               = new HashSet <string>(this.ExistingNodesAndEdges);
            HashSet <string> temporaryPredicates            = new HashSet <string>(this.ExistingPredicateLinks);
            List <Tuple <PredicateLink, int> > forwardLinks = new List <Tuple <PredicateLink, int> >();

            // priority = 1
            // retrieve traversalLink and add predicates
            if (traversalLink != null && !this.ExistingNodesAndEdges.Contains(traversalLink.LinkAlias))
            {
                // Find predicates that can be evaluated after retrieving this traversalLink
                if (traversalLink is MatchEdge)
                {
                    temporaryAliases.Add(traversalLink.LinkAlias);
                }
                else if (traversalLink is PredicateLink)
                {
                    temporaryPredicates.Add(traversalLink.LinkAlias);
                }
                else
                {
                    throw new QueryCompilationException("Cannot support " + traversalLink + " as a traversal link or an edge");
                }

                foreach (Tuple <PredicateLink, HashSet <string> > tuple in predicateLinksAccessedTableAliases)
                {
                    if (!temporaryPredicates.Contains(tuple.Item1.LinkAlias) &&
                        temporaryAliases.IsSupersetOf(tuple.Item2))
                    {
                        temporaryPredicates.Add(tuple.Item1.LinkAlias);
                        forwardLinks.Add(new Tuple <PredicateLink, int>(tuple.Item1, 1));
                    }
                }

                // Make sure the all existing edges and this traversalLink are consistent
                // Because all existing edges are consistent, we just need make one exstring edge and this traversalLink consistent
                MatchNode matchNode = node as MatchNode;
                WColumnReferenceExpression nodeColumnReferenceExprFromTraversalLink  = GetNodeColumnReferenceExprFromLink(traversalLink);
                WColumnReferenceExpression nodeColumnReferenceExprFromAnExistingEdge = GetNodeColumnReferenceExprFromAnExistingEdge(matchNode, this.ExistingNodesAndEdges);
                if (nodeColumnReferenceExprFromTraversalLink != null &&
                    nodeColumnReferenceExprFromAnExistingEdge != null)
                {
                    forwardLinks.Add(
                        new Tuple <PredicateLink, int>(
                            new PredicateLink(
                                SqlUtil.GetEqualBooleanComparisonExpr(nodeColumnReferenceExprFromTraversalLink,
                                                                      nodeColumnReferenceExprFromAnExistingEdge)), 1));
                }
            }

            // priority = 2
            // retrieve node and some edges and add predicates
            temporaryAliases.Add(node.NodeAlias);
            foreach (Tuple <MatchEdge, int> tuple in backwardEdges)
            {
                if (tuple.Item2 == 2)
                {
                    temporaryAliases.Add(tuple.Item1.LinkAlias);
                    MatchNode otherNode = tuple.Item1.SinkNode;
                    WColumnReferenceExpression nodeColumnReferenceExprFromBackwardEdge   = null;
                    WColumnReferenceExpression nodeColumnReferenceExprFromAnExistingEdge = GetNodeColumnReferenceExprFromAnExistingEdge(otherNode, this.ExistingNodesAndEdges);
                    if (nodeColumnReferenceExprFromAnExistingEdge != null)
                    {
                        foreach (MatchEdge edge in otherNode.Neighbors)
                        {
                            if (edge.LinkAlias == tuple.Item1.LinkAlias)
                            {
                                nodeColumnReferenceExprFromBackwardEdge = GetNodeColumnReferenceExprFromLink(edge);
                                break;
                            }
                        }
                        if (nodeColumnReferenceExprFromBackwardEdge == null)
                        {
                            foreach (MatchEdge edge in otherNode.ReverseNeighbors)
                            {
                                if (edge.LinkAlias == tuple.Item1.LinkAlias)
                                {
                                    nodeColumnReferenceExprFromBackwardEdge = GetNodeColumnReferenceExprFromLink(edge);
                                    break;
                                }
                            }
                        }
                        if (nodeColumnReferenceExprFromBackwardEdge == null)
                        {
                            foreach (MatchEdge edge in otherNode.DanglingEdges)
                            {
                                if (edge.LinkAlias == tuple.Item1.LinkAlias)
                                {
                                    nodeColumnReferenceExprFromBackwardEdge = GetNodeColumnReferenceExprFromLink(edge);
                                    break;
                                }
                            }
                        }
                    }
                    // Because all existing edges are consistent, we just need make one exstring edge and this edge consistent
                    if (nodeColumnReferenceExprFromBackwardEdge != null &&
                        nodeColumnReferenceExprFromAnExistingEdge != null)
                    {
                        temporaryPredicates.Add(tuple.Item1.LinkAlias);
                        forwardLinks.Add(
                            new Tuple <PredicateLink, int>(
                                new PredicateLink(
                                    SqlUtil.GetEqualBooleanComparisonExpr(nodeColumnReferenceExprFromBackwardEdge,
                                                                          nodeColumnReferenceExprFromAnExistingEdge)), 2));
                    }
                }
            }

            // Check predicates
            foreach (Tuple <PredicateLink, HashSet <string> > tuple in predicateLinksAccessedTableAliases)
            {
                if (!temporaryPredicates.Contains(tuple.Item1.LinkAlias) &&
                    temporaryAliases.IsSupersetOf(tuple.Item2))
                {
                    temporaryPredicates.Add(tuple.Item1.LinkAlias);
                    forwardLinks.Add(new Tuple <PredicateLink, int>(tuple.Item1, 2));
                }
            }

            // priority = 3
            // retrieve another edges and add predicates
            foreach (Tuple <MatchEdge, int> tuple in backwardEdges)
            {
                if (tuple.Item2 == 3)
                {
                    temporaryAliases.Add(tuple.Item1.LinkAlias);
                    MatchNode otherNode = tuple.Item1.SinkNode;
                    WColumnReferenceExpression nodeColumnReferenceExprFromBackwardEdge   = null;
                    WColumnReferenceExpression nodeColumnReferenceExprFromAnExistingEdge = GetNodeColumnReferenceExprFromAnExistingEdge(otherNode, this.ExistingNodesAndEdges);
                    if (nodeColumnReferenceExprFromAnExistingEdge != null)
                    {
                        foreach (MatchEdge edge in otherNode.Neighbors)
                        {
                            if (edge.LinkAlias == tuple.Item1.LinkAlias)
                            {
                                nodeColumnReferenceExprFromBackwardEdge = GetNodeColumnReferenceExprFromLink(edge);
                                break;
                            }
                        }
                        if (nodeColumnReferenceExprFromBackwardEdge == null)
                        {
                            foreach (MatchEdge edge in otherNode.ReverseNeighbors)
                            {
                                if (edge.LinkAlias == tuple.Item1.LinkAlias)
                                {
                                    nodeColumnReferenceExprFromBackwardEdge = GetNodeColumnReferenceExprFromLink(edge);
                                    break;
                                }
                            }
                        }
                        if (nodeColumnReferenceExprFromBackwardEdge == null)
                        {
                            foreach (MatchEdge edge in otherNode.DanglingEdges)
                            {
                                if (edge.LinkAlias == tuple.Item1.LinkAlias)
                                {
                                    nodeColumnReferenceExprFromBackwardEdge = GetNodeColumnReferenceExprFromLink(edge);
                                    break;
                                }
                            }
                        }
                    }
                    // Because all existing edges are consistent, we just need make one exstring edge and this edge consistent
                    if (nodeColumnReferenceExprFromBackwardEdge != null &&
                        nodeColumnReferenceExprFromAnExistingEdge != null)
                    {
                        temporaryPredicates.Add(tuple.Item1.LinkAlias);
                        forwardLinks.Add(
                            new Tuple <PredicateLink, int>(
                                new PredicateLink(
                                    SqlUtil.GetEqualBooleanComparisonExpr(nodeColumnReferenceExprFromBackwardEdge,
                                                                          nodeColumnReferenceExprFromAnExistingEdge)), 3));
                    }
                }
            }

            // Check predicates
            foreach (Tuple <PredicateLink, HashSet <string> > tuple in predicateLinksAccessedTableAliases)
            {
                if (!temporaryPredicates.Contains(tuple.Item1.LinkAlias) &&
                    temporaryAliases.IsSupersetOf(tuple.Item2))
                {
                    temporaryPredicates.Add(tuple.Item1.LinkAlias);
                    forwardLinks.Add(new Tuple <PredicateLink, int>(tuple.Item1, 3));
                }
            }
            return(forwardLinks);
        }
Example #3
0
        /// <summary>
        /// Given a node, we need to find it possible traversalLink, forwardLinks and backwardEdges
        /// </summary>
        /// <param name="predicateLinksAccessedTableAliases"></param>
        /// <param name="node"></param>
        /// <returns></returns>
        private List <Tuple <CompileNode, CompileLink, List <Tuple <PredicateLink, int> >, List <Tuple <MatchEdge, int> >, List <ExecutionOrder> > > GenerateTuples(
            List <Tuple <PredicateLink, HashSet <string> > > predicateLinksAccessedTableAliases,
            CompileNode node)
        {
            List <Tuple <CompileNode, CompileLink, List <Tuple <PredicateLink, int> >, List <Tuple <MatchEdge, int> >, List <ExecutionOrder> > > nextTuples =
                new List <Tuple <CompileNode, CompileLink, List <Tuple <PredicateLink, int> >, List <Tuple <MatchEdge, int> >, List <ExecutionOrder> > >();

            // Find local execution orders
            List <ExecutionOrder> localExecutionOrders = node.GetLocalExecutionOrder(this).Order.First().Item5;
            // traversalLinks must be existing edges, ready edges or WEdgeVertexBridgeExpression.
            List <CompileLink> traversalLinks        = new List <CompileLink>();
            List <MatchEdge>   connectedReadyEdges   = new List <MatchEdge>();
            List <MatchEdge>   connectedUnreadyEdges = new List <MatchEdge>();

            // The item2 is the corresponding priority.
            // If the priority is 1,
            //  then the edge should try to retrieve before retrieve a node or execute a TVF,
            //  and predicates should be evaluated after retrieving the edge
            // If the priority is 2,
            //  then edges should try to retrieve when retrieving a node (not support in execution part now),
            //  and predicates should be evaluated after retrieving these edges and a node or executing a TVF
            // If the priority is 3,
            //  then edges should try to retrieve after retrieving a node,
            //  and predicates should be evaluated after retrieving these edges
            List <Tuple <PredicateLink, int> > forwardLinks  = new List <Tuple <PredicateLink, int> >();
            List <Tuple <MatchEdge, int> >     backwardEdges = new List <Tuple <MatchEdge, int> >();

            // Find forwardLinks, backwardEdges and predicates after adding the alias of node
            if (node is MatchNode)
            {
                MatchNode matchNode = node as MatchNode;

                foreach (MatchEdge edge in matchNode.Neighbors)
                {
                    if (!this.ExistingNodesAndEdges.Contains(edge.LinkAlias))
                    {
                        if (this.ReadyEdges.Contains(edge.LinkAlias))
                        {
                            connectedReadyEdges.Add(edge);
                        }
                        else
                        {
                            connectedUnreadyEdges.Add(edge);
                        }
                    }
                    if (this.ExistingNodesAndEdges.Contains(edge.LinkAlias) || this.ReadyEdges.Contains(edge.LinkAlias))
                    {
                        traversalLinks.Add(edge);
                    }
                }
                foreach (MatchEdge edge in matchNode.ReverseNeighbors)
                {
                    if (!this.ExistingNodesAndEdges.Contains(edge.LinkAlias))
                    {
                        if (this.ReadyEdges.Contains(edge.LinkAlias))
                        {
                            connectedReadyEdges.Add(edge);
                        }
                        else
                        {
                            connectedUnreadyEdges.Add(edge);
                        }
                    }
                    if (this.ExistingNodesAndEdges.Contains(edge.LinkAlias) || this.ReadyEdges.Contains(edge.LinkAlias))
                    {
                        traversalLinks.Add(edge);
                    }
                }
                foreach (MatchEdge edge in matchNode.DanglingEdges)
                {
                    if (!this.ExistingNodesAndEdges.Contains(edge.LinkAlias))
                    {
                        connectedUnreadyEdges.Add(edge);
                    }
                }

                // Add the node's alias temporarily to find WEdgeVertexBridgeExpression
                HashSet <string> temporaryAliases = new HashSet <string>(this.ExistingNodesAndEdges);
                temporaryAliases.Add(matchNode.NodeAlias);
                foreach (Tuple <PredicateLink, HashSet <string> > tuple in predicateLinksAccessedTableAliases)
                {
                    if (!this.ExistingPredicateLinks.Contains(tuple.Item1.LinkAlias) &&
                        temporaryAliases.IsSupersetOf(tuple.Item2) &&
                        tuple.Item1.BooleanExpression is WEdgeVertexBridgeExpression)
                    {
                        traversalLinks.Add(tuple.Item1);
                    }
                }

                // Find all possible sublists of connectedUnreadyEdges
                // Because we may not reterieve all edges at this step
                List <List <MatchEdge> > connectedUnreadyEdgesSublists = GetAllSublists(connectedUnreadyEdges);

                // if traversalLinks is empty, we add a NULL in it.
                if (!traversalLinks.Any())
                {
                    traversalLinks.Add(null);
                }

                // backwardEdges = (connectedReadyEdges) U (a sublist of connectedUnreadyEdges) - (traversalLink)
                // but connnectedREadyEdges' priorities can be 2 or 3, connectedUnreadyEdges must be 2
                foreach (CompileLink traversalLink in traversalLinks)
                {
                    foreach (List <MatchEdge> connectedUnreadyEdgesSublist in connectedUnreadyEdgesSublists)
                    {
                        List <MatchEdge> connectedReadyEdgesSublist = new List <MatchEdge>(connectedReadyEdges);
                        if (traversalLink is MatchEdge)
                        {
                            connectedReadyEdgesSublist.Remove(traversalLink as MatchEdge);
                        }

                        // Find all combinations of connectedReadyEdges
                        // These readyEdges' priorities can be 2 or 3
                        List <List <Tuple <MatchEdge, int> > > connectedReadyEdgesCombinations = GetAllCombinations(connectedReadyEdgesSublist, new List <int>()
                        {
                            2, 3
                        });
                        // Find all combinations of connectedUnreadyEdges
                        // All unreadyEdges' priorities must be 2 if retrieving them
                        List <List <Tuple <MatchEdge, int> > > connectedUnreadyEdgesCombinations = GetAllCombinations(connectedUnreadyEdgesSublist, new List <int>()
                        {
                            2
                        });

                        // Find all combinations of connectedReadyEdges and connectedUnreadyEdges
                        foreach (List <Tuple <MatchEdge, int> > connectedReadyEdgesCombination in connectedReadyEdgesCombinations)
                        {
                            foreach (List <Tuple <MatchEdge, int> > connectedUnreadyEdgesCombination in connectedUnreadyEdgesCombinations)
                            {
                                backwardEdges = new List <Tuple <MatchEdge, int> >(connectedReadyEdgesCombination);
                                backwardEdges.AddRange(connectedUnreadyEdgesCombination);
                                forwardLinks = this.FindPredicates(matchNode, traversalLink, backwardEdges, predicateLinksAccessedTableAliases);
                                nextTuples.Add(
                                    new Tuple <CompileNode, CompileLink, List <Tuple <PredicateLink, int> >,
                                               List <Tuple <MatchEdge, int> >, List <ExecutionOrder> >(matchNode,
                                                                                                       traversalLink, forwardLinks, backwardEdges, localExecutionOrders));
                            }
                        }
                    }
                }
            }
            else if (node is NonFreeTable)
            {
                forwardLinks = this.FindPredicates(node, null, backwardEdges, predicateLinksAccessedTableAliases);
                nextTuples.Add(new Tuple <CompileNode, CompileLink, List <Tuple <PredicateLink, int> >, List <Tuple <MatchEdge, int> >, List <ExecutionOrder> >(
                                   node, null, forwardLinks, backwardEdges, localExecutionOrders));
            }
            else
            {
                throw new QueryCompilationException("Can't find " + node.ToString() + " in AggregationBlock");
            }

            return(nextTuples);
        }