private static WColumnReferenceExpression GetNodeColumnReferenceExprFromLink(CompileLink link) { if (link is MatchEdge) { MatchEdge edge = link as MatchEdge; if (edge.EdgeType == WEdgeType.OutEdge) { return(SqlUtil.GetColumnReferenceExpr(edge.LinkAlias, edge.IsReversed ? GremlinKeyword.EdgeSinkV : GremlinKeyword.EdgeSourceV)); } else if (edge.EdgeType == WEdgeType.InEdge) { return(SqlUtil.GetColumnReferenceExpr(edge.LinkAlias, edge.IsReversed ? GremlinKeyword.EdgeSourceV : GremlinKeyword.EdgeSinkV)); } else { return(SqlUtil.GetColumnReferenceExpr(edge.LinkAlias, GremlinKeyword.EdgeOtherV)); } } else if (link is PredicateLink) { PredicateLink predicateLink = link as PredicateLink; if (predicateLink.BooleanExpression is WEdgeVertexBridgeExpression) { return((predicateLink.BooleanExpression as WEdgeVertexBridgeExpression).FirstExpr as WColumnReferenceExpression); } } throw new QueryCompilationException("Cannot support " + link + " as a traversal link or an edge"); }
/// <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); }