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); }
/// <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); }
/// <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); }